From a8f828a066773a59fdf646299359d35ae0e845af Mon Sep 17 00:00:00 2001 From: wyatt8740 Date: Mon, 6 Jan 2014 12:02:16 -0500 Subject: Removed accidental upload of copyrighted map files --- WinQuake/3dfx.txt | 136 +- WinQuake/README.Solaris | 196 +- WinQuake/WinQuake.dsp | 4480 +++++++-------- WinQuake/WinQuake.dsw | 88 +- WinQuake/WinQuake.plg | 1190 ++-- WinQuake/adivtab.h | 2154 ++++---- WinQuake/anorm_dots.h | 38 +- WinQuake/anorms.h | 362 +- WinQuake/asm_draw.h | 38 +- WinQuake/asm_i386.h | 38 +- WinQuake/block16.h | 38 +- WinQuake/block8.h | 38 +- WinQuake/bspfile.h | 648 +-- WinQuake/cd_audio.c | 1772 +++--- WinQuake/cd_linux.c | 38 +- WinQuake/cd_null.c | 108 +- WinQuake/cd_win.c | 954 ++-- WinQuake/cdaudio.h | 54 +- WinQuake/chase.c | 184 +- WinQuake/cl_demo.c | 734 +-- WinQuake/cl_input.c | 896 +-- WinQuake/cl_main.c | 1514 ++--- WinQuake/cl_parse.c | 38 +- WinQuake/cl_tent.c | 788 +-- WinQuake/clean.bat | 36 +- WinQuake/client.h | 750 +-- WinQuake/cmd.c | 1410 ++--- WinQuake/cmd.h | 242 +- WinQuake/common.c | 3654 ++++++------- WinQuake/common.h | 366 +- WinQuake/conproc.c | 730 +-- WinQuake/conproc.h | 74 +- WinQuake/console.c | 1298 ++--- WinQuake/console.h | 92 +- WinQuake/crc.c | 160 +- WinQuake/crc.h | 48 +- WinQuake/cvar.c | 448 +- WinQuake/cvar.h | 194 +- WinQuake/d_draw.s | 38 +- WinQuake/d_draw16.s | 38 +- WinQuake/d_edge.c | 662 +-- WinQuake/d_fill.c | 176 +- WinQuake/d_iface.h | 458 +- WinQuake/d_ifacea.h | 38 +- WinQuake/d_init.c | 346 +- WinQuake/d_local.h | 222 +- WinQuake/d_modech.c | 214 +- WinQuake/d_part.c | 414 +- WinQuake/d_parta.s | 38 +- WinQuake/d_polysa.s | 38 +- WinQuake/d_polyse.c | 2222 ++++---- WinQuake/d_scan.c | 898 +-- WinQuake/d_scana.s | 38 +- WinQuake/d_sky.c | 276 +- WinQuake/d_spr8.s | 38 +- WinQuake/d_sprite.c | 884 +-- WinQuake/d_surf.c | 670 +-- WinQuake/d_vars.c | 100 +- WinQuake/d_varsa.s | 38 +- WinQuake/d_zpoint.c | 94 +- WinQuake/data/COMEXP.TXT | 974 ++-- WinQuake/data/HELP.TXT | 238 +- WinQuake/data/LICINFO.TXT | 194 +- WinQuake/data/ORDER.TXT | 206 +- WinQuake/data/README.TXT | 912 ++-- WinQuake/data/RLICNSE.TXT | 408 +- WinQuake/data/SLICNSE.TXT | 350 +- WinQuake/debugi386/bin/id1/config.cfg | 84 - WinQuake/debugi386/bin/id1/glquake/armor.ms2 | Bin 1836 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/backpack.ms2 | Bin 2032 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/bolt.ms2 | Bin 688 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/bolt2.ms2 | Bin 520 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/bolt3.ms2 | Bin 520 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/demon.ms2 | Bin 5384 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/eyes.ms2 | Bin 316 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/flame.ms2 | Bin 2540 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/flame2.ms2 | Bin 1800 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/g_nail.ms2 | Bin 4748 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/g_rock.ms2 | Bin 3748 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/g_shot.ms2 | Bin 1748 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/gib1.ms2 | Bin 600 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/gib2.ms2 | Bin 1780 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/gib3.ms2 | Bin 420 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/grenade.ms2 | Bin 320 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/h_demon.ms2 | Bin 1676 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/h_ogre.ms2 | Bin 732 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/h_player.ms2 | Bin 828 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/h_wizard.ms2 | Bin 544 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/h_zombie.ms2 | Bin 936 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/invisibl.ms2 | Bin 916 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/lavaball.ms2 | Bin 420 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/missile.ms2 | Bin 1296 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/ogre.ms2 | Bin 6192 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/player.ms2 | Bin 7988 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/s_spike.ms2 | Bin 116 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/spike.ms2 | Bin 116 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_axe.ms2 | Bin 3676 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_light.ms2 | Bin 3616 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_nail.ms2 | Bin 4004 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_nail2.ms2 | Bin 3860 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_rock.ms2 | Bin 1108 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_rock2.ms2 | Bin 2620 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_shot.ms2 | Bin 2416 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/v_shot2.ms2 | Bin 3208 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/w_g_key.ms2 | Bin 2496 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/w_spike.ms2 | Bin 1936 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/wizard.ms2 | Bin 3100 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/zom_gib.ms2 | Bin 420 -> 0 bytes WinQuake/debugi386/bin/id1/glquake/zombie.ms2 | Bin 7144 -> 0 bytes WinQuake/debugi386/bin/id1/pak0.pak | Bin 18276119 -> 0 bytes WinQuake/debugi386/bin/id1/pak1.pak | Bin 34257856 -> 0 bytes WinQuake/dos_v2.c | 514 +- WinQuake/dosisms.h | 200 +- WinQuake/draw.c | 38 +- WinQuake/draw.h | 80 +- WinQuake/dxsdk/SDK/INC/D3D.H | 784 +-- WinQuake/dxsdk/SDK/INC/D3DCAPS.H | 580 +- WinQuake/dxsdk/SDK/INC/D3DRM.H | 268 +- WinQuake/dxsdk/SDK/INC/D3DRMDEF.H | 804 +-- WinQuake/dxsdk/SDK/INC/D3DRMOBJ.H | 1454 ++--- WinQuake/dxsdk/SDK/INC/D3DRMWIN.H | 96 +- WinQuake/dxsdk/SDK/INC/D3DTYPES.H | 1912 +++---- WinQuake/dxsdk/SDK/INC/DDRAW.H | 6204 ++++++++++----------- WinQuake/dxsdk/SDK/INC/DINPUT.H | 1746 +++--- WinQuake/dxsdk/SDK/INC/DPLAY.H | 616 +-- WinQuake/dxsdk/SDK/INC/DSETUP.H | 132 +- WinQuake/dxsdk/SDK/INC/DSOUND.H | 732 +-- WinQuake/dxsdk/SDK/INC/FASTFILE.H | 48 +- WinQuake/gas2masm/gas2masm.c | 2112 +++---- WinQuake/gas2masm/gas2masm.dsp | 200 +- WinQuake/gas2masm/gas2masm.dsw | 58 +- WinQuake/gas2masm/gas2masm.plg | 64 +- WinQuake/gl_draw.c | 40 +- WinQuake/gl_mesh.c | 720 +-- WinQuake/gl_model.c | 38 +- WinQuake/gl_model.h | 860 +-- WinQuake/gl_refrag.c | 40 +- WinQuake/gl_rlight.c | 236 +- WinQuake/gl_rmain.c | 2318 ++++---- WinQuake/gl_rmisc.c | 38 +- WinQuake/gl_rsurf.c | 38 +- WinQuake/gl_screen.c | 40 +- WinQuake/gl_test.c | 364 +- WinQuake/gl_vidlinux.c | 1732 +++--- WinQuake/gl_vidlinuxglx.c | 1995 +++---- WinQuake/gl_vidnt.c | 4 +- WinQuake/gl_warp.c | 2184 ++++---- WinQuake/gl_warp_sin.h | 38 +- WinQuake/glqnotes.txt | 342 +- WinQuake/glquake.h | 38 +- WinQuake/glquake2.h | 418 +- WinQuake/host.c | 38 +- WinQuake/host_cmd.c | 38 +- WinQuake/in_dos.c | 1230 ++--- WinQuake/in_null.c | 78 +- WinQuake/in_sun.c | 38 +- WinQuake/in_win.c | 2478 ++++----- WinQuake/input.h | 68 +- WinQuake/keys.c | 1518 ++--- WinQuake/keys.h | 266 +- WinQuake/kit/3DFX.TXT | 556 +- WinQuake/kit/JOYSTICK.TXT | 324 +- WinQuake/kit/README.TXT | 342 +- WinQuake/makezip.bat | 2 +- WinQuake/math.s | 38 +- WinQuake/mathlib.c | 1170 ++-- WinQuake/mathlib.h | 38 +- WinQuake/menu.c | 56 +- WinQuake/menu.h | 76 +- WinQuake/model.c | 3748 ++++++------- WinQuake/model.h | 764 +-- WinQuake/modelgen.h | 268 +- WinQuake/mpdosock.h | 1594 +++--- WinQuake/mplib.c | 444 +- WinQuake/mplpc.c | 2002 +++---- WinQuake/net.h | 38 +- WinQuake/net_bsd.c | 186 +- WinQuake/net_bw.c | 1526 +++--- WinQuake/net_bw.h | 78 +- WinQuake/net_comx.c | 2570 ++++----- WinQuake/net_dgrm.c | 2780 +++++----- WinQuake/net_dgrm.h | 68 +- WinQuake/net_dos.c | 324 +- WinQuake/net_ipx.c | 1412 ++--- WinQuake/net_ipx.h | 78 +- WinQuake/net_loop.c | 490 +- WinQuake/net_loop.h | 66 +- WinQuake/net_main.c | 1994 +++---- WinQuake/net_mp.c | 886 +-- WinQuake/net_mp.h | 78 +- WinQuake/net_none.c | 92 +- WinQuake/net_ser.c | 1902 +++---- WinQuake/net_ser.h | 66 +- WinQuake/net_udp.c | 38 +- WinQuake/net_udp.h | 78 +- WinQuake/net_vcr.c | 334 +- WinQuake/net_vcr.h | 74 +- WinQuake/net_win.c | 240 +- WinQuake/net_wins.c | 1150 ++-- WinQuake/net_wins.h | 78 +- WinQuake/net_wipx.c | 864 +-- WinQuake/net_wipx.h | 78 +- WinQuake/nonintel.c | 128 +- WinQuake/pr_cmds.c | 3868 ++++++------- WinQuake/pr_comp.h | 360 +- WinQuake/pr_edict.c | 2212 ++++---- WinQuake/pr_exec.c | 1336 ++--- WinQuake/progdefs.h | 48 +- WinQuake/progdefs.q1 | 286 +- WinQuake/progdefs.q2 | 316 +- WinQuake/progs.h | 268 +- WinQuake/protocol.h | 334 +- WinQuake/q.bat | 2 +- WinQuake/qa.bat | 2 +- WinQuake/qb.bat | 2 +- WinQuake/qt.bat | 2 +- WinQuake/quake-data.spec.sh | 0 WinQuake/quake-hipnotic.spec.sh | 0 WinQuake/quake-rogue.spec.sh | 0 WinQuake/quake-shareware.spec.sh | 0 WinQuake/quake.spec.sh | 0 WinQuake/quakeasm.h | 38 +- WinQuake/quakedef.h | 38 +- WinQuake/r_aclip.c | 700 +-- WinQuake/r_aclipa.s | 38 +- WinQuake/r_alias.c | 1506 ++--- WinQuake/r_aliasa.s | 38 +- WinQuake/r_bsp.c | 1348 ++--- WinQuake/r_draw.c | 1816 +++--- WinQuake/r_drawa.s | 38 +- WinQuake/r_edge.c | 1548 +++--- WinQuake/r_edgea.s | 38 +- WinQuake/r_efrag.c | 552 +- WinQuake/r_light.c | 520 +- WinQuake/r_local.h | 630 +-- WinQuake/r_main.c | 2170 ++++---- WinQuake/r_misc.c | 1046 ++-- WinQuake/r_part.c | 1600 +++--- WinQuake/r_shared.h | 314 +- WinQuake/r_sky.c | 560 +- WinQuake/r_sprite.c | 802 +-- WinQuake/r_surf.c | 1356 ++--- WinQuake/r_vars.c | 78 +- WinQuake/r_varsa.s | 38 +- WinQuake/render.h | 316 +- WinQuake/resource.h | 40 +- WinQuake/sbar.c | 38 +- WinQuake/sbar.h | 78 +- WinQuake/scitech/INCLUDE/DEBUG.H | 580 +- WinQuake/scitech/INCLUDE/MGLDOS.H | 166 +- WinQuake/scitech/INCLUDE/MGLWIN.H | 304 +- WinQuake/scitech/INCLUDE/MGRAPH.H | 3902 ++++++------- WinQuake/screen.c | 1982 +++---- WinQuake/screen.h | 114 +- WinQuake/server.h | 514 +- WinQuake/snd_dma.c | 2034 +++---- WinQuake/snd_dos.c | 1306 ++--- WinQuake/snd_gus.c | 2586 ++++----- WinQuake/snd_linux.c | 38 +- WinQuake/snd_mem.c | 682 +-- WinQuake/snd_mix.c | 796 +-- WinQuake/snd_mixa.s | 38 +- WinQuake/snd_next.c | 110 +- WinQuake/snd_null.c | 194 +- WinQuake/snd_sun.c | 38 +- WinQuake/snd_win.c | 1458 ++--- WinQuake/sound.h | 354 +- WinQuake/spritegn.h | 220 +- WinQuake/surf16.s | 38 +- WinQuake/surf8.s | 38 +- WinQuake/sv_main.c | 2400 ++++---- WinQuake/sv_move.c | 854 +-- WinQuake/sv_phys.c | 3234 +++++------ WinQuake/sv_user.c | 1258 ++--- WinQuake/sys.h | 142 +- WinQuake/sys_dos.c | 1906 +++---- WinQuake/sys_linux.c | 2 +- WinQuake/sys_null.c | 464 +- WinQuake/sys_sun.c | 38 +- WinQuake/sys_win.c | 1786 +++--- WinQuake/sys_wina.s | 38 +- WinQuake/sys_wind.c | 650 +-- WinQuake/vgamodes.h | 1198 ++-- WinQuake/vid.h | 170 +- WinQuake/vid_dos.c | 1556 +++--- WinQuake/vid_dos.h | 166 +- WinQuake/vid_ext.c | 1590 +++--- WinQuake/vid_null.c | 174 +- WinQuake/vid_sunx.c | 38 +- WinQuake/vid_sunxil.c | 38 +- WinQuake/vid_svgalib.c | 38 +- WinQuake/vid_vga.c | 956 ++-- WinQuake/vid_win.c | 6686 +++++++++++------------ WinQuake/vid_x.c | 38 +- WinQuake/view.c | 2226 ++++---- WinQuake/view.h | 70 +- WinQuake/vregset.c | 162 +- WinQuake/vregset.h | 112 +- WinQuake/wad.c | 316 +- WinQuake/wad.h | 150 +- WinQuake/winquake.h | 228 +- WinQuake/winquake.rc | 262 +- WinQuake/world.c | 1924 +++---- WinQuake/world.h | 156 +- WinQuake/worlda.s | 38 +- WinQuake/wq.bat | 84 +- WinQuake/wqreadme.txt | 2238 ++++---- WinQuake/zone.c | 1870 +++---- WinQuake/zone.h | 262 +- 309 files changed, 90787 insertions(+), 90870 deletions(-) delete mode 100644 WinQuake/debugi386/bin/id1/config.cfg delete mode 100644 WinQuake/debugi386/bin/id1/glquake/armor.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/backpack.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/bolt.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/bolt2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/bolt3.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/demon.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/eyes.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/flame.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/flame2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/g_nail.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/g_rock.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/g_shot.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/gib1.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/gib2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/gib3.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/grenade.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/h_demon.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/h_ogre.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/h_player.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/h_wizard.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/h_zombie.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/invisibl.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/lavaball.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/missile.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/ogre.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/player.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/s_spike.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/spike.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_axe.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_light.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_nail.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_nail2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_rock.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_rock2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_shot.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/v_shot2.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/w_g_key.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/w_spike.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/wizard.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/zom_gib.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/glquake/zombie.ms2 delete mode 100644 WinQuake/debugi386/bin/id1/pak0.pak delete mode 100644 WinQuake/debugi386/bin/id1/pak1.pak mode change 100644 => 100755 WinQuake/quake-data.spec.sh mode change 100644 => 100755 WinQuake/quake-hipnotic.spec.sh mode change 100644 => 100755 WinQuake/quake-rogue.spec.sh mode change 100644 => 100755 WinQuake/quake-shareware.spec.sh mode change 100644 => 100755 WinQuake/quake.spec.sh (limited to 'WinQuake') diff --git a/WinQuake/3dfx.txt b/WinQuake/3dfx.txt index 404aa9a..5598d92 100644 --- a/WinQuake/3dfx.txt +++ b/WinQuake/3dfx.txt @@ -1,69 +1,69 @@ -GLQuake Drivers - -Graphics Subsystem: Voodoo Graphics or Voodoo Rush - -Copyright ( 1997 3Dfx Interactive, Inc. ) -All Rights Reserved - -3Dfx Interactive, Inc. -www: www.3dfx.com -news: news.3dfx.com - ------------------------------------------------------------------------ -NOTE: GLQuake requires DirectX support DirectSound. DirectX can be -installed from the media provided with your Voodoo Based 3D Accelerator. - -Glide 2.31 or HIGHER runtime drivers *MUST* be installed to use this -GLQuake driver. Please download these drivers from your board -manufacturer OR unsupported drivers from http://www.3dfx.com ------------------------------------------------------------------------ - -Release Notes for GLQuake's mini-GL driver - -What's in the distribution? ---------------------------- - -This distribution contains GLQuake Drivers for Voodoo Based 3D -Accelerators. These drivers were tested on the following boards: - -Voodoo Graphics: -- Quantum 3D Obsidian -- Diamond Monster 3D -- Orchid Righteous 3D -- Deltron Realvision Flash 3D -- Guillemot MaxiGamer -- Skywell Magic 3D - -Voodoo Rush: -- Hercules Stringray 128-3D -- Intergraph Intense 3D Voodoo -- Jazz Multimedia Adrenaline Rush - -NOTE: The enclosed drivers are not meant to replace any Direct3D or -Glide drivers provided by your Voodoo Graphics card manufacturer. -Please obtain supported drivers from your board manufacturer. - -OEMSR2 and NT users: Do NOT replace OPENGL32.DLL located in your -Windows\SYSTEM directory. - -Requirements ------------- - -- Voodoo Graphics or Voodoo Rush Based 3D Accelerator -- Windows 95 (Windows NT is supported for Voodoo Rush) -- A PC with a Pentium 90 or higher CPU -- 16MB of RAM -- 2D Video card set at 16 bit color - -Support and Frequently Asked Questions --------------------------------------- - -GLQuake is currently unsupported. You may however find answers to -questions on various Quake dedicated websites. 3Dfx provides a GLQuake -newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to -discuss GLQuake with other users. 3Dfx also provides a regularly -updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html - - -Voodoo Graphics and Voodoo Rush are trademarks of 3Dfx Interactive, Inc. +GLQuake Drivers + +Graphics Subsystem: Voodoo Graphics or Voodoo Rush + +Copyright ( 1997 3Dfx Interactive, Inc. ) +All Rights Reserved + +3Dfx Interactive, Inc. +www: www.3dfx.com +news: news.3dfx.com + +----------------------------------------------------------------------- +NOTE: GLQuake requires DirectX support DirectSound. DirectX can be +installed from the media provided with your Voodoo Based 3D Accelerator. + +Glide 2.31 or HIGHER runtime drivers *MUST* be installed to use this +GLQuake driver. Please download these drivers from your board +manufacturer OR unsupported drivers from http://www.3dfx.com +----------------------------------------------------------------------- + +Release Notes for GLQuake's mini-GL driver + +What's in the distribution? +--------------------------- + +This distribution contains GLQuake Drivers for Voodoo Based 3D +Accelerators. These drivers were tested on the following boards: + +Voodoo Graphics: +- Quantum 3D Obsidian +- Diamond Monster 3D +- Orchid Righteous 3D +- Deltron Realvision Flash 3D +- Guillemot MaxiGamer +- Skywell Magic 3D + +Voodoo Rush: +- Hercules Stringray 128-3D +- Intergraph Intense 3D Voodoo +- Jazz Multimedia Adrenaline Rush + +NOTE: The enclosed drivers are not meant to replace any Direct3D or +Glide drivers provided by your Voodoo Graphics card manufacturer. +Please obtain supported drivers from your board manufacturer. + +OEMSR2 and NT users: Do NOT replace OPENGL32.DLL located in your +Windows\SYSTEM directory. + +Requirements +------------ + +- Voodoo Graphics or Voodoo Rush Based 3D Accelerator +- Windows 95 (Windows NT is supported for Voodoo Rush) +- A PC with a Pentium 90 or higher CPU +- 16MB of RAM +- 2D Video card set at 16 bit color + +Support and Frequently Asked Questions +-------------------------------------- + +GLQuake is currently unsupported. You may however find answers to +questions on various Quake dedicated websites. 3Dfx provides a GLQuake +newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to +discuss GLQuake with other users. 3Dfx also provides a regularly +updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html + + +Voodoo Graphics and Voodoo Rush are trademarks of 3Dfx Interactive, Inc. All other trademarks are the property of their respective owners. \ No newline at end of file diff --git a/WinQuake/README.Solaris b/WinQuake/README.Solaris index 6d52ed0..5867b46 100644 --- a/WinQuake/README.Solaris +++ b/WinQuake/README.Solaris @@ -1,98 +1,98 @@ -Solaris 2 Quake / QuakeWorld ----------------------------- - - This is an UNSUPPORTED version of Quake and QuakeWorld. Don't - bother id software about it. Bug reports will be ignored. - -PORT DETAILS ------------- - - There are a few major difference between this port and the - vanilla Quake/QuakeWorld available on the internet. For - optimum performance, you should copy everything to a directory - on your local system before starting play so that you are - not mounting files from a remote filesystem. - - In order to use this program, you need the files pak0.pak - and pak1.pak in the id1 directory found on a registered copy of - Quake. You can ftp them to your Solaris host from a Windows95 - machine for example. The files must be in an id1 subdirectory from - the directory you install Quake/QuakeWorld, and all file names must - be lowercase. Add on packages such as ThreeWave CTF work fine as - well, just place such addon packages in their own directory as you - would on a Windows95 installation. But again, make sure all files - are lowercase. - - COMMAND LINE FLAGS: - - +pixel_multiply - - You can magnify the screen by using this flag: - - Ex: % quake +pixel_multiply 2 - - You can also use this command (without the dash) - from the Quake console. pixel_multiply is a Quake - cvar and is saved from session to session in the - config.cfg file. - - -winsize - - Set the size of the window when you start - - -count_frames - - See how many frames per second you're getting - - GAME SETTINGS - - mouse binding - - You can bind and unbind the mouse to the Quake window - by using the Use Mouse selection in the Options menu, - or with the "_windowed_mouse" command in the console, - ex "_windowed_mouse 1" Now, moving the mouse will move - your player. Use "_windowed_mouse 0" to unbind. You - can bind or alias this to a key. - - Example command: - - % quake.xil +pixel_multiply 2 -winsize 400 300 - -WHAT IS "QUAKEWORLD" AND HOW DO I USE IT? ------------------------------------------ - - In a nutshell, QuakeWorld is an extension of Quake that is - much more user friendly. It allows the user to dynamically - download changes from the server, such as new maps and new - weapons while inside the Quake client. It is not directly - compatible with Quake (ie, you can't connect to a Quake server - from a QuakeWorld client) but in general it is superior to - Quake. QuakeWorld also offers much smoother play over the - Internet by using client prediction. For more information, - check out http://www.quakeworld.net/. - - In order to use it, you must make a copy of the "qw" - directory. Any new stuff that is downloaded from a QuakeWorld - server will be stored in this directory. All regular Quake - flags apply so you can use the same command line as before. - - Example command: - - % qwcl.xil +pixel_multiply 2 -winsize 400 300 - -WHERE CAN I FIND OUT ABOUT... ------------------------------ - - If you've got questions about Quake, rest assured that there - are answers out there. Try checking out these web sites: - - http://www.planetquake.com/ - http://www.stomped.com/ - http://www.quakeworld.net/ - - If all else fails use a search engine. - -Happy fragging, -the Quake/Solaris team - +Solaris 2 Quake / QuakeWorld +---------------------------- + + This is an UNSUPPORTED version of Quake and QuakeWorld. Don't + bother id software about it. Bug reports will be ignored. + +PORT DETAILS +------------ + + There are a few major difference between this port and the + vanilla Quake/QuakeWorld available on the internet. For + optimum performance, you should copy everything to a directory + on your local system before starting play so that you are + not mounting files from a remote filesystem. + + In order to use this program, you need the files pak0.pak + and pak1.pak in the id1 directory found on a registered copy of + Quake. You can ftp them to your Solaris host from a Windows95 + machine for example. The files must be in an id1 subdirectory from + the directory you install Quake/QuakeWorld, and all file names must + be lowercase. Add on packages such as ThreeWave CTF work fine as + well, just place such addon packages in their own directory as you + would on a Windows95 installation. But again, make sure all files + are lowercase. + + COMMAND LINE FLAGS: + + +pixel_multiply + + You can magnify the screen by using this flag: + + Ex: % quake +pixel_multiply 2 + + You can also use this command (without the dash) + from the Quake console. pixel_multiply is a Quake + cvar and is saved from session to session in the + config.cfg file. + + -winsize + + Set the size of the window when you start + + -count_frames + + See how many frames per second you're getting + + GAME SETTINGS + + mouse binding + + You can bind and unbind the mouse to the Quake window + by using the Use Mouse selection in the Options menu, + or with the "_windowed_mouse" command in the console, + ex "_windowed_mouse 1" Now, moving the mouse will move + your player. Use "_windowed_mouse 0" to unbind. You + can bind or alias this to a key. + + Example command: + + % quake.xil +pixel_multiply 2 -winsize 400 300 + +WHAT IS "QUAKEWORLD" AND HOW DO I USE IT? +----------------------------------------- + + In a nutshell, QuakeWorld is an extension of Quake that is + much more user friendly. It allows the user to dynamically + download changes from the server, such as new maps and new + weapons while inside the Quake client. It is not directly + compatible with Quake (ie, you can't connect to a Quake server + from a QuakeWorld client) but in general it is superior to + Quake. QuakeWorld also offers much smoother play over the + Internet by using client prediction. For more information, + check out http://www.quakeworld.net/. + + In order to use it, you must make a copy of the "qw" + directory. Any new stuff that is downloaded from a QuakeWorld + server will be stored in this directory. All regular Quake + flags apply so you can use the same command line as before. + + Example command: + + % qwcl.xil +pixel_multiply 2 -winsize 400 300 + +WHERE CAN I FIND OUT ABOUT... +----------------------------- + + If you've got questions about Quake, rest assured that there + are answers out there. Try checking out these web sites: + + http://www.planetquake.com/ + http://www.stomped.com/ + http://www.quakeworld.net/ + + If all else fails use a search engine. + +Happy fragging, +the Quake/Solaris team + diff --git a/WinQuake/WinQuake.dsp b/WinQuake/WinQuake.dsp index 4b0792f..48fc0b7 100644 --- a/WinQuake/WinQuake.dsp +++ b/WinQuake/WinQuake.dsp @@ -1,2240 +1,2240 @@ -# Microsoft Developer Studio Project File - Name="winquake" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Application" 0x0101 - -CFG=winquake - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "WinQuake.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "WinQuake.mak" CFG="winquake - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "winquake - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "winquake - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE "winquake - Win32 GL Debug" (based on "Win32 (x86) Application") -!MESSAGE "winquake - Win32 GL Release" (based on "Win32 (x86) Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\Release" -# PROP BASE Intermediate_Dir ".\Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir ".\Release" -# PROP Intermediate_Dir ".\Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c -# SUBTRACT CPP /Oa /Og -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 -# SUBTRACT LINK32 /map /debug - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir ".\Debug" -# PROP BASE Intermediate_Dir ".\Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir ".\Debug" -# PROP Intermediate_Dir ".\Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 -# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 -# SUBTRACT LINK32 /nodefaultlib - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir ".\winquake" -# PROP BASE Intermediate_Dir ".\winquake" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir ".\debug_gl" -# PROP Intermediate_Dir ".\debug_gl" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G5 /ML /GX /Zi /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /debug /machine:I386 -# SUBTRACT BASE LINK32 /nodefaultlib -# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:".\debug_gl\glquake.exe" -# SUBTRACT LINK32 /nodefaultlib - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\winquak0" -# PROP BASE Intermediate_Dir ".\winquak0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir ".\release_gl" -# PROP Intermediate_Dir ".\release_gl" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# SUBTRACT BASE CPP /Oa /Og -# ADD CPP /nologo /G5 /GX /Ot /Ow /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /profile /machine:I386 -# SUBTRACT BASE LINK32 /map /debug -# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\release_gl\glquake.exe" -# SUBTRACT LINK32 /map /debug - -!ENDIF - -# Begin Target - -# Name "winquake - Win32 Release" -# Name "winquake - Win32 Debug" -# Name "winquake - Win32 GL Debug" -# Name "winquake - Win32 GL Release" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=.\cd_win.c -# End Source File -# Begin Source File - -SOURCE=.\chase.c -# End Source File -# Begin Source File - -SOURCE=.\cl_demo.c -# End Source File -# Begin Source File - -SOURCE=.\cl_input.c -# End Source File -# Begin Source File - -SOURCE=.\cl_main.c -# End Source File -# Begin Source File - -SOURCE=.\cl_parse.c -# End Source File -# Begin Source File - -SOURCE=.\cl_tent.c -# End Source File -# Begin Source File - -SOURCE=.\cmd.c -# End Source File -# Begin Source File - -SOURCE=.\common.c -# End Source File -# Begin Source File - -SOURCE=.\conproc.c -# End Source File -# Begin Source File - -SOURCE=.\console.c -# End Source File -# Begin Source File - -SOURCE=.\crc.c -# End Source File -# Begin Source File - -SOURCE=.\cvar.c -# End Source File -# Begin Source File - -SOURCE=.\d_draw.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_draw.s -InputName=d_draw - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_draw.s -InputName=d_draw - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_draw16.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_draw16.s -InputName=d_draw16 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_draw16.s -InputName=d_draw16 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_edge.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_fill.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_init.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_modech.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_part.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_parta.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_parta.s -InputName=d_parta - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_parta.s -InputName=d_parta - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_polysa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_polysa.s -InputName=d_polysa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_polysa.s -InputName=d_polysa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_polyse.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_scan.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_scana.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_scana.s -InputName=d_scana - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_scana.s -InputName=d_scana - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_sky.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_spr8.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_spr8.s -InputName=d_spr8 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_spr8.s -InputName=d_spr8 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_sprite.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_surf.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_vars.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_varsa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\d_varsa.s -InputName=d_varsa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\d_varsa.s -InputName=d_varsa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\d_zpoint.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\draw.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_draw.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_mesh.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_model.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_refrag.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_rlight.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_rmain.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_rmisc.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_rsurf.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_screen.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_test.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_vidnt.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\gl_warp.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\host.c -# End Source File -# Begin Source File - -SOURCE=.\host_cmd.c -# End Source File -# Begin Source File - -SOURCE=.\in_win.c -# End Source File -# Begin Source File - -SOURCE=.\keys.c -# End Source File -# Begin Source File - -SOURCE=.\math.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\math.s -InputName=math - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\math.s -InputName=math - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\debug_gl -InputPath=.\math.s -InputName=math - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\release_gl -InputPath=.\math.s -InputName=math - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\mathlib.c -# End Source File -# Begin Source File - -SOURCE=.\menu.c -# End Source File -# Begin Source File - -SOURCE=.\model.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\net_dgrm.c -# End Source File -# Begin Source File - -SOURCE=.\net_loop.c -# End Source File -# Begin Source File - -SOURCE=.\net_main.c -# End Source File -# Begin Source File - -SOURCE=.\net_vcr.c -# End Source File -# Begin Source File - -SOURCE=.\net_win.c -# End Source File -# Begin Source File - -SOURCE=.\net_wins.c -# End Source File -# Begin Source File - -SOURCE=.\net_wipx.c -# End Source File -# Begin Source File - -SOURCE=.\pr_cmds.c -# End Source File -# Begin Source File - -SOURCE=.\pr_edict.c -# End Source File -# Begin Source File - -SOURCE=.\pr_exec.c -# End Source File -# Begin Source File - -SOURCE=.\r_aclip.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_aclipa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\r_aclipa.s -InputName=r_aclipa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\r_aclipa.s -InputName=r_aclipa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_alias.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_aliasa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\r_aliasa.s -InputName=r_aliasa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\r_aliasa.s -InputName=r_aliasa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_bsp.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_draw.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_drawa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\r_drawa.s -InputName=r_drawa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\r_drawa.s -InputName=r_drawa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_edge.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_edgea.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\r_edgea.s -InputName=r_edgea - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\r_edgea.s -InputName=r_edgea - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_efrag.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_light.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_main.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_misc.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_part.c -# End Source File -# Begin Source File - -SOURCE=.\r_sky.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_sprite.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_surf.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_vars.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\r_varsa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\r_varsa.s -InputName=r_varsa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\r_varsa.s -InputName=r_varsa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\sbar.c -# End Source File -# Begin Source File - -SOURCE=.\screen.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\snd_dma.c -# End Source File -# Begin Source File - -SOURCE=.\snd_mem.c -# End Source File -# Begin Source File - -SOURCE=.\snd_mix.c -# End Source File -# Begin Source File - -SOURCE=.\snd_mixa.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\snd_mixa.s -InputName=snd_mixa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\snd_mixa.s -InputName=snd_mixa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\debug_gl -InputPath=.\snd_mixa.s -InputName=snd_mixa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\release_gl -InputPath=.\snd_mixa.s -InputName=snd_mixa - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\snd_win.c -# End Source File -# Begin Source File - -SOURCE=.\surf16.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\surf16.s -InputName=surf16 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\surf16.s -InputName=surf16 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\surf8.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\surf8.s -InputName=surf8 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\surf8.s -InputName=surf8 - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\sv_main.c -# End Source File -# Begin Source File - -SOURCE=.\sv_move.c -# End Source File -# Begin Source File - -SOURCE=.\sv_phys.c -# End Source File -# Begin Source File - -SOURCE=.\sv_user.c -# End Source File -# Begin Source File - -SOURCE=.\sys_win.c -# End Source File -# Begin Source File - -SOURCE=.\sys_wina.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\sys_wina.s -InputName=sys_wina - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\sys_wina.s -InputName=sys_wina - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\debug_gl -InputPath=.\sys_wina.s -InputName=sys_wina - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\release_gl -InputPath=.\sys_wina.s -InputName=sys_wina - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\vid_win.c - -!IF "$(CFG)" == "winquake - Win32 Release" - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# PROP Exclude_From_Build 1 - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\view.c -# End Source File -# Begin Source File - -SOURCE=.\wad.c -# End Source File -# Begin Source File - -SOURCE=.\winquake.rc -# End Source File -# Begin Source File - -SOURCE=.\world.c -# End Source File -# Begin Source File - -SOURCE=.\worlda.s - -!IF "$(CFG)" == "winquake - Win32 Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\Release -InputPath=.\worlda.s -InputName=worlda - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\Debug -InputPath=.\worlda.s -InputName=worlda - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" - -# Begin Custom Build - mycoolbuild -OutDir=.\debug_gl -InputPath=.\worlda.s -InputName=worlda - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" - -# Begin Custom Build - mycoolbuild -OutDir=.\release_gl -InputPath=.\worlda.s -InputName=worlda - -"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) - gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm - ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm - del $(OUTDIR)\$(InputName).spp - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\zone.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\anorm_dots.h -# End Source File -# Begin Source File - -SOURCE=.\anorms.h -# End Source File -# Begin Source File - -SOURCE=.\bspfile.h -# End Source File -# Begin Source File - -SOURCE=.\cdaudio.h -# End Source File -# Begin Source File - -SOURCE=.\client.h -# End Source File -# Begin Source File - -SOURCE=.\cmd.h -# End Source File -# Begin Source File - -SOURCE=.\common.h -# End Source File -# Begin Source File - -SOURCE=.\conproc.h -# End Source File -# Begin Source File - -SOURCE=.\console.h -# End Source File -# Begin Source File - -SOURCE=.\crc.h -# End Source File -# Begin Source File - -SOURCE=.\cvar.h -# End Source File -# Begin Source File - -SOURCE=.\d_iface.h -# End Source File -# Begin Source File - -SOURCE=.\dosisms.h -# End Source File -# Begin Source File - -SOURCE=.\draw.h -# End Source File -# Begin Source File - -SOURCE=.\gl_model.h -# End Source File -# Begin Source File - -SOURCE=.\gl_warp_sin.h -# End Source File -# Begin Source File - -SOURCE=.\glquake.h -# End Source File -# Begin Source File - -SOURCE=.\input.h -# End Source File -# Begin Source File - -SOURCE=.\keys.h -# End Source File -# Begin Source File - -SOURCE=.\mathlib.h -# End Source File -# Begin Source File - -SOURCE=.\menu.h -# End Source File -# Begin Source File - -SOURCE=.\model.h -# End Source File -# Begin Source File - -SOURCE=.\modelgen.h -# End Source File -# Begin Source File - -SOURCE=.\net.h -# End Source File -# Begin Source File - -SOURCE=.\net_dgrm.h -# End Source File -# Begin Source File - -SOURCE=.\net_loop.h -# End Source File -# Begin Source File - -SOURCE=.\net_ser.h -# End Source File -# Begin Source File - -SOURCE=.\net_vcr.h -# End Source File -# Begin Source File - -SOURCE=.\net_wins.h -# End Source File -# Begin Source File - -SOURCE=.\net_wipx.h -# End Source File -# Begin Source File - -SOURCE=.\pr_comp.h -# End Source File -# Begin Source File - -SOURCE=.\progdefs.h -# End Source File -# Begin Source File - -SOURCE=.\progs.h -# End Source File -# Begin Source File - -SOURCE=.\protocol.h -# End Source File -# Begin Source File - -SOURCE=.\quakedef.h -# End Source File -# Begin Source File - -SOURCE=.\r_local.h -# End Source File -# Begin Source File - -SOURCE=.\r_shared.h -# End Source File -# Begin Source File - -SOURCE=.\render.h -# End Source File -# Begin Source File - -SOURCE=.\sbar.h -# End Source File -# Begin Source File - -SOURCE=.\screen.h -# End Source File -# Begin Source File - -SOURCE=.\server.h -# End Source File -# Begin Source File - -SOURCE=.\sound.h -# End Source File -# Begin Source File - -SOURCE=.\spritegn.h -# End Source File -# Begin Source File - -SOURCE=.\sys.h -# End Source File -# Begin Source File - -SOURCE=.\vid.h -# End Source File -# Begin Source File - -SOURCE=.\view.h -# End Source File -# Begin Source File - -SOURCE=.\wad.h -# End Source File -# Begin Source File - -SOURCE=.\winquake.h -# End Source File -# Begin Source File - -SOURCE=.\world.h -# End Source File -# Begin Source File - -SOURCE=.\zone.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\qe3.ico -# End Source File -# Begin Source File - -SOURCE=.\quake.ico -# End Source File -# End Group -# Begin Source File - -SOURCE=.\progdefs.q1 -# End Source File -# Begin Source File - -SOURCE=.\progdefs.q2 -# End Source File -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="winquake" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=winquake - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "WinQuake.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "WinQuake.mak" CFG="winquake - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "winquake - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "winquake - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "winquake - Win32 GL Debug" (based on "Win32 (x86) Application") +!MESSAGE "winquake - Win32 GL Release" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c +# SUBTRACT CPP /Oa /Og +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 +# SUBTRACT LINK32 /map /debug + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\winquake" +# PROP BASE Intermediate_Dir ".\winquake" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\debug_gl" +# PROP Intermediate_Dir ".\debug_gl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /ML /GX /Zi /Od /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /ML /GX /ZI /Od /I ".\dxsdk\sdk\inc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /debug /machine:I386 +# SUBTRACT BASE LINK32 /nodefaultlib +# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:".\debug_gl\glquake.exe" +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\winquak0" +# PROP BASE Intermediate_Dir ".\winquak0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\release_gl" +# PROP Intermediate_Dir ".\release_gl" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# SUBTRACT BASE CPP /Oa /Og +# ADD CPP /nologo /G5 /GX /Ot /Ow /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "GLQUAKE" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib .\scitech\lib\win32\vc\mgllt.lib /nologo /subsystem:windows /profile /machine:I386 +# SUBTRACT BASE LINK32 /map /debug +# ADD LINK32 .\dxsdk\sdk\lib\dxguid.lib comctl32.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\release_gl\glquake.exe" +# SUBTRACT LINK32 /map /debug + +!ENDIF + +# Begin Target + +# Name "winquake - Win32 Release" +# Name "winquake - Win32 Debug" +# Name "winquake - Win32 GL Debug" +# Name "winquake - Win32 GL Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\cd_win.c +# End Source File +# Begin Source File + +SOURCE=.\chase.c +# End Source File +# Begin Source File + +SOURCE=.\cl_demo.c +# End Source File +# Begin Source File + +SOURCE=.\cl_input.c +# End Source File +# Begin Source File + +SOURCE=.\cl_main.c +# End Source File +# Begin Source File + +SOURCE=.\cl_parse.c +# End Source File +# Begin Source File + +SOURCE=.\cl_tent.c +# End Source File +# Begin Source File + +SOURCE=.\cmd.c +# End Source File +# Begin Source File + +SOURCE=.\common.c +# End Source File +# Begin Source File + +SOURCE=.\conproc.c +# End Source File +# Begin Source File + +SOURCE=.\console.c +# End Source File +# Begin Source File + +SOURCE=.\crc.c +# End Source File +# Begin Source File + +SOURCE=.\cvar.c +# End Source File +# Begin Source File + +SOURCE=.\d_draw.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_draw.s +InputName=d_draw + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_draw.s +InputName=d_draw + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_draw16.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_draw16.s +InputName=d_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_draw16.s +InputName=d_draw16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_edge.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_fill.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_init.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_modech.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_part.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_parta.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_parta.s +InputName=d_parta + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_parta.s +InputName=d_parta + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_polysa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_polysa.s +InputName=d_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_polysa.s +InputName=d_polysa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_polyse.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_scan.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_scana.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_scana.s +InputName=d_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_scana.s +InputName=d_scana + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_sky.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_spr8.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_spr8.s +InputName=d_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_spr8.s +InputName=d_spr8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_sprite.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_surf.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_vars.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_varsa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\d_varsa.s +InputName=d_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\d_varsa.s +InputName=d_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\d_zpoint.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\draw.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_draw.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_mesh.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_model.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_refrag.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_rlight.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_rmain.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_rmisc.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_rsurf.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_screen.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_test.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_vidnt.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gl_warp.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\host.c +# End Source File +# Begin Source File + +SOURCE=.\host_cmd.c +# End Source File +# Begin Source File + +SOURCE=.\in_win.c +# End Source File +# Begin Source File + +SOURCE=.\keys.c +# End Source File +# Begin Source File + +SOURCE=.\math.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\debug_gl +InputPath=.\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\release_gl +InputPath=.\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\mathlib.c +# End Source File +# Begin Source File + +SOURCE=.\menu.c +# End Source File +# Begin Source File + +SOURCE=.\model.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\net_dgrm.c +# End Source File +# Begin Source File + +SOURCE=.\net_loop.c +# End Source File +# Begin Source File + +SOURCE=.\net_main.c +# End Source File +# Begin Source File + +SOURCE=.\net_vcr.c +# End Source File +# Begin Source File + +SOURCE=.\net_win.c +# End Source File +# Begin Source File + +SOURCE=.\net_wins.c +# End Source File +# Begin Source File + +SOURCE=.\net_wipx.c +# End Source File +# Begin Source File + +SOURCE=.\pr_cmds.c +# End Source File +# Begin Source File + +SOURCE=.\pr_edict.c +# End Source File +# Begin Source File + +SOURCE=.\pr_exec.c +# End Source File +# Begin Source File + +SOURCE=.\r_aclip.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aclipa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\r_aclipa.s +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\r_aclipa.s +InputName=r_aclipa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_alias.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_aliasa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\r_aliasa.s +InputName=r_aliasa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\r_aliasa.s +InputName=r_aliasa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_bsp.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_draw.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_drawa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\r_drawa.s +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\r_drawa.s +InputName=r_drawa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edge.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_edgea.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\r_edgea.s +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\r_edgea.s +InputName=r_edgea + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_efrag.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_light.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_main.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_misc.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_part.c +# End Source File +# Begin Source File + +SOURCE=.\r_sky.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_sprite.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_surf.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_vars.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\r_varsa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\r_varsa.s +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\r_varsa.s +InputName=r_varsa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\sbar.c +# End Source File +# Begin Source File + +SOURCE=.\screen.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\snd_dma.c +# End Source File +# Begin Source File + +SOURCE=.\snd_mem.c +# End Source File +# Begin Source File + +SOURCE=.\snd_mix.c +# End Source File +# Begin Source File + +SOURCE=.\snd_mixa.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\snd_mixa.s +InputName=snd_mixa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\snd_mixa.s +InputName=snd_mixa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\debug_gl +InputPath=.\snd_mixa.s +InputName=snd_mixa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\release_gl +InputPath=.\snd_mixa.s +InputName=snd_mixa + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\snd_win.c +# End Source File +# Begin Source File + +SOURCE=.\surf16.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\surf16.s +InputName=surf16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\surf16.s +InputName=surf16 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\surf8.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\surf8.s +InputName=surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\surf8.s +InputName=surf8 + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\sv_main.c +# End Source File +# Begin Source File + +SOURCE=.\sv_move.c +# End Source File +# Begin Source File + +SOURCE=.\sv_phys.c +# End Source File +# Begin Source File + +SOURCE=.\sv_user.c +# End Source File +# Begin Source File + +SOURCE=.\sys_win.c +# End Source File +# Begin Source File + +SOURCE=.\sys_wina.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\debug_gl +InputPath=.\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\release_gl +InputPath=.\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\vid_win.c + +!IF "$(CFG)" == "winquake - Win32 Release" + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\view.c +# End Source File +# Begin Source File + +SOURCE=.\wad.c +# End Source File +# Begin Source File + +SOURCE=.\winquake.rc +# End Source File +# Begin Source File + +SOURCE=.\world.c +# End Source File +# Begin Source File + +SOURCE=.\worlda.s + +!IF "$(CFG)" == "winquake - Win32 Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\Release +InputPath=.\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\Debug +InputPath=.\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Debug" + +# Begin Custom Build - mycoolbuild +OutDir=.\debug_gl +InputPath=.\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "winquake - Win32 GL Release" + +# Begin Custom Build - mycoolbuild +OutDir=.\release_gl +InputPath=.\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /DGLQUAKE > $(OUTDIR)\$(InputName).spp $(InputPath) + gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zone.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\anorm_dots.h +# End Source File +# Begin Source File + +SOURCE=.\anorms.h +# End Source File +# Begin Source File + +SOURCE=.\bspfile.h +# End Source File +# Begin Source File + +SOURCE=.\cdaudio.h +# End Source File +# Begin Source File + +SOURCE=.\client.h +# End Source File +# Begin Source File + +SOURCE=.\cmd.h +# End Source File +# Begin Source File + +SOURCE=.\common.h +# End Source File +# Begin Source File + +SOURCE=.\conproc.h +# End Source File +# Begin Source File + +SOURCE=.\console.h +# End Source File +# Begin Source File + +SOURCE=.\crc.h +# End Source File +# Begin Source File + +SOURCE=.\cvar.h +# End Source File +# Begin Source File + +SOURCE=.\d_iface.h +# End Source File +# Begin Source File + +SOURCE=.\dosisms.h +# End Source File +# Begin Source File + +SOURCE=.\draw.h +# End Source File +# Begin Source File + +SOURCE=.\gl_model.h +# End Source File +# Begin Source File + +SOURCE=.\gl_warp_sin.h +# End Source File +# Begin Source File + +SOURCE=.\glquake.h +# End Source File +# Begin Source File + +SOURCE=.\input.h +# End Source File +# Begin Source File + +SOURCE=.\keys.h +# End Source File +# Begin Source File + +SOURCE=.\mathlib.h +# End Source File +# Begin Source File + +SOURCE=.\menu.h +# End Source File +# Begin Source File + +SOURCE=.\model.h +# End Source File +# Begin Source File + +SOURCE=.\modelgen.h +# End Source File +# Begin Source File + +SOURCE=.\net.h +# End Source File +# Begin Source File + +SOURCE=.\net_dgrm.h +# End Source File +# Begin Source File + +SOURCE=.\net_loop.h +# End Source File +# Begin Source File + +SOURCE=.\net_ser.h +# End Source File +# Begin Source File + +SOURCE=.\net_vcr.h +# End Source File +# Begin Source File + +SOURCE=.\net_wins.h +# End Source File +# Begin Source File + +SOURCE=.\net_wipx.h +# End Source File +# Begin Source File + +SOURCE=.\pr_comp.h +# End Source File +# Begin Source File + +SOURCE=.\progdefs.h +# End Source File +# Begin Source File + +SOURCE=.\progs.h +# End Source File +# Begin Source File + +SOURCE=.\protocol.h +# End Source File +# Begin Source File + +SOURCE=.\quakedef.h +# End Source File +# Begin Source File + +SOURCE=.\r_local.h +# End Source File +# Begin Source File + +SOURCE=.\r_shared.h +# End Source File +# Begin Source File + +SOURCE=.\render.h +# End Source File +# Begin Source File + +SOURCE=.\sbar.h +# End Source File +# Begin Source File + +SOURCE=.\screen.h +# End Source File +# Begin Source File + +SOURCE=.\server.h +# End Source File +# Begin Source File + +SOURCE=.\sound.h +# End Source File +# Begin Source File + +SOURCE=.\spritegn.h +# End Source File +# Begin Source File + +SOURCE=.\sys.h +# End Source File +# Begin Source File + +SOURCE=.\vid.h +# End Source File +# Begin Source File + +SOURCE=.\view.h +# End Source File +# Begin Source File + +SOURCE=.\wad.h +# End Source File +# Begin Source File + +SOURCE=.\winquake.h +# End Source File +# Begin Source File + +SOURCE=.\world.h +# End Source File +# Begin Source File + +SOURCE=.\zone.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\qe3.ico +# End Source File +# Begin Source File + +SOURCE=.\quake.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\progdefs.q1 +# End Source File +# Begin Source File + +SOURCE=.\progdefs.q2 +# End Source File +# End Target +# End Project diff --git a/WinQuake/WinQuake.dsw b/WinQuake/WinQuake.dsw index b95a3f3..2a47987 100644 --- a/WinQuake/WinQuake.dsw +++ b/WinQuake/WinQuake.dsw @@ -1,44 +1,44 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "gas2masm"=.\gas2masm\gas2masm.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "winquake"=.\WinQuake.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name gas2masm - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gas2masm"=.\gas2masm\gas2masm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "winquake"=.\WinQuake.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name gas2masm + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/WinQuake/WinQuake.plg b/WinQuake/WinQuake.plg index c7b9979..386cc3d 100644 --- a/WinQuake/WinQuake.plg +++ b/WinQuake/WinQuake.plg @@ -1,595 +1,595 @@ - - -
-

Build Log

-

---------------------Configuration: winquake - Win32 Release-------------------- -

-

Command Lines

-Creating temporary file "C:\TEMP\RSP74A.bat" with contents -[ -@echo off -cl /EP > .\Release\worlda.spp .\worlda.s -gas2masm\debug\gas2masm < .\Release\worlda.spp > .\Release\worlda.asm -ml /c /Cp /coff /Fo.\Release\worlda.obj /Zm /Zi .\Release\worlda.asm -del .\Release\worlda.spp -] -Creating command line "C:\TEMP\RSP74A.bat" -Creating temporary file "C:\TEMP\RSP74B.bat" with contents -[ -@echo off -cl /EP > .\Release\sys_wina.spp .\sys_wina.s -gas2masm\debug\gas2masm < .\Release\sys_wina.spp > .\Release\sys_wina.asm -ml /c /Cp /coff /Fo.\Release\sys_wina.obj /Zm /Zi .\Release\sys_wina.asm -del .\Release\sys_wina.spp -] -Creating command line "C:\TEMP\RSP74B.bat" -Creating temporary file "C:\TEMP\RSP74C.bat" with contents -[ -@echo off -cl /EP > .\Release\surf8.spp .\surf8.s -gas2masm\debug\gas2masm < .\Release\surf8.spp > .\Release\surf8.asm -ml /c /Cp /coff /Fo.\Release\surf8.obj /Zm /Zi .\Release\surf8.asm -del .\Release\surf8.spp -] -Creating command line "C:\TEMP\RSP74C.bat" -Creating temporary file "C:\TEMP\RSP74D.bat" with contents -[ -@echo off -cl /EP > .\Release\surf16.spp .\surf16.s -gas2masm\debug\gas2masm < .\Release\surf16.spp > .\Release\surf16.asm -ml /c /Cp /coff /Fo.\Release\surf16.obj /Zm /Zi .\Release\surf16.asm -del .\Release\surf16.spp -] -Creating command line "C:\TEMP\RSP74D.bat" -Creating temporary file "C:\TEMP\RSP74E.bat" with contents -[ -@echo off -cl /EP > .\Release\snd_mixa.spp .\snd_mixa.s -gas2masm\debug\gas2masm < .\Release\snd_mixa.spp > .\Release\snd_mixa.asm -ml /c /Cp /coff /Fo.\Release\snd_mixa.obj /Zm /Zi .\Release\snd_mixa.asm -del .\Release\snd_mixa.spp -] -Creating command line "C:\TEMP\RSP74E.bat" -Creating temporary file "C:\TEMP\RSP74F.bat" with contents -[ -@echo off -cl /EP > .\Release\r_varsa.spp .\r_varsa.s -gas2masm\debug\gas2masm < .\Release\r_varsa.spp > .\Release\r_varsa.asm -ml /c /Cp /coff /Fo.\Release\r_varsa.obj /Zm /Zi .\Release\r_varsa.asm -del .\Release\r_varsa.spp -] -Creating command line "C:\TEMP\RSP74F.bat" -Creating temporary file "C:\TEMP\RSP750.bat" with contents -[ -@echo off -cl /EP > .\Release\r_edgea.spp .\r_edgea.s -gas2masm\debug\gas2masm < .\Release\r_edgea.spp > .\Release\r_edgea.asm -ml /c /Cp /coff /Fo.\Release\r_edgea.obj /Zm /Zi .\Release\r_edgea.asm -del .\Release\r_edgea.spp -] -Creating command line "C:\TEMP\RSP750.bat" -Creating temporary file "C:\TEMP\RSP751.bat" with contents -[ -@echo off -cl /EP > .\Release\r_drawa.spp .\r_drawa.s -gas2masm\debug\gas2masm < .\Release\r_drawa.spp > .\Release\r_drawa.asm -ml /c /Cp /coff /Fo.\Release\r_drawa.obj /Zm /Zi .\Release\r_drawa.asm -del .\Release\r_drawa.spp -] -Creating command line "C:\TEMP\RSP751.bat" -Creating temporary file "C:\TEMP\RSP752.bat" with contents -[ -@echo off -cl /EP > .\Release\r_aliasa.spp .\r_aliasa.s -gas2masm\debug\gas2masm < .\Release\r_aliasa.spp > .\Release\r_aliasa.asm -ml /c /Cp /coff /Fo.\Release\r_aliasa.obj /Zm /Zi .\Release\r_aliasa.asm -del .\Release\r_aliasa.spp -] -Creating command line "C:\TEMP\RSP752.bat" -Creating temporary file "C:\TEMP\RSP753.bat" with contents -[ -@echo off -cl /EP > .\Release\r_aclipa.spp .\r_aclipa.s -gas2masm\debug\gas2masm < .\Release\r_aclipa.spp > .\Release\r_aclipa.asm -ml /c /Cp /coff /Fo.\Release\r_aclipa.obj /Zm /Zi .\Release\r_aclipa.asm -del .\Release\r_aclipa.spp -] -Creating command line "C:\TEMP\RSP753.bat" -Creating temporary file "C:\TEMP\RSP754.bat" with contents -[ -@echo off -cl /EP > .\Release\math.spp .\math.s -gas2masm\debug\gas2masm < .\Release\math.spp > .\Release\math.asm -ml /c /Cp /coff /Fo.\Release\math.obj /Zm /Zi .\Release\math.asm -del .\Release\math.spp -] -Creating command line "C:\TEMP\RSP754.bat" -Creating temporary file "C:\TEMP\RSP755.bat" with contents -[ -@echo off -cl /EP > .\Release\d_varsa.spp .\d_varsa.s -gas2masm\debug\gas2masm < .\Release\d_varsa.spp > .\Release\d_varsa.asm -ml /c /Cp /coff /Fo.\Release\d_varsa.obj /Zm /Zi .\Release\d_varsa.asm -del .\Release\d_varsa.spp -] -Creating command line "C:\TEMP\RSP755.bat" -Creating temporary file "C:\TEMP\RSP756.bat" with contents -[ -@echo off -cl /EP > .\Release\d_spr8.spp .\d_spr8.s -gas2masm\debug\gas2masm < .\Release\d_spr8.spp > .\Release\d_spr8.asm -ml /c /Cp /coff /Fo.\Release\d_spr8.obj /Zm /Zi .\Release\d_spr8.asm -del .\Release\d_spr8.spp -] -Creating command line "C:\TEMP\RSP756.bat" -Creating temporary file "C:\TEMP\RSP757.bat" with contents -[ -@echo off -cl /EP > .\Release\d_scana.spp .\d_scana.s -gas2masm\debug\gas2masm < .\Release\d_scana.spp > .\Release\d_scana.asm -ml /c /Cp /coff /Fo.\Release\d_scana.obj /Zm /Zi .\Release\d_scana.asm -del .\Release\d_scana.spp -] -Creating command line "C:\TEMP\RSP757.bat" -Creating temporary file "C:\TEMP\RSP758.bat" with contents -[ -@echo off -cl /EP > .\Release\d_polysa.spp .\d_polysa.s -gas2masm\debug\gas2masm < .\Release\d_polysa.spp > .\Release\d_polysa.asm -ml /c /Cp /coff /Fo.\Release\d_polysa.obj /Zm /Zi .\Release\d_polysa.asm -del .\Release\d_polysa.spp -] -Creating command line "C:\TEMP\RSP758.bat" -Creating temporary file "C:\TEMP\RSP759.bat" with contents -[ -@echo off -cl /EP > .\Release\d_parta.spp .\d_parta.s -gas2masm\debug\gas2masm < .\Release\d_parta.spp > .\Release\d_parta.asm -ml /c /Cp /coff /Fo.\Release\d_parta.obj /Zm /Zi .\Release\d_parta.asm -del .\Release\d_parta.spp -] -Creating command line "C:\TEMP\RSP759.bat" -Creating temporary file "C:\TEMP\RSP75A.bat" with contents -[ -@echo off -cl /EP > .\Release\d_draw16.spp .\d_draw16.s -gas2masm\debug\gas2masm < .\Release\d_draw16.spp > .\Release\d_draw16.asm -ml /c /Cp /coff /Fo.\Release\d_draw16.obj /Zm /Zi .\Release\d_draw16.asm -del .\Release\d_draw16.spp -] -Creating command line "C:\TEMP\RSP75A.bat" -Creating temporary file "C:\TEMP\RSP75B.bat" with contents -[ -@echo off -cl /EP > .\Release\d_draw.spp .\d_draw.s -gas2masm\debug\gas2masm < .\Release\d_draw.spp > .\Release\d_draw.asm -ml /c /Cp /coff /Fo.\Release\d_draw.obj /Zm /Zi .\Release\d_draw.asm -del .\Release\d_draw.spp -] -Creating command line "C:\TEMP\RSP75B.bat" -Creating command line "rc.exe /l 0x409 /fo".\Release/winquake.res" /d "NDEBUG" "D:\Work\quake source\WinQuake\winquake.rc"" -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -worlda.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\worlda.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -sys_wina.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\sys_wina.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -surf8.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\surf8.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -surf16.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\surf16.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -snd_mixa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\snd_mixa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -r_varsa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\r_varsa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -r_edgea.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\r_edgea.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -r_drawa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\r_drawa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -r_aliasa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\r_aliasa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -r_aclipa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\r_aclipa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -math.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\math.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_varsa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_varsa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_spr8.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_spr8.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_scana.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_scana.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_polysa.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_polysa.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_parta.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_parta.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_draw16.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_draw16.asm -mycoolbuild -Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 -Copyright (C) Microsoft Corp 1984-1998. All rights reserved. - -d_draw.s -Microsoft (R) Macro Assembler Version 6.11 -Copyright (C) Microsoft Corp 1981-1993. All rights reserved. - - Assembling: .\Release\d_draw.asm -Creating temporary file "C:\TEMP\RSP75C.tmp" with contents -[ -/nologo /G5 /ML /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR".\Release/" /Fp".\Release/WinQuake.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c -"D:\Work\quake source\WinQuake\cd_win.c" -"D:\Work\quake source\WinQuake\chase.c" -"D:\Work\quake source\WinQuake\cl_demo.c" -"D:\Work\quake source\WinQuake\cl_input.c" -"D:\Work\quake source\WinQuake\cl_main.c" -"D:\Work\quake source\WinQuake\cl_parse.c" -"D:\Work\quake source\WinQuake\cl_tent.c" -"D:\Work\quake source\WinQuake\cmd.c" -"D:\Work\quake source\WinQuake\common.c" -"D:\Work\quake source\WinQuake\conproc.c" -"D:\Work\quake source\WinQuake\console.c" -"D:\Work\quake source\WinQuake\crc.c" -"D:\Work\quake source\WinQuake\cvar.c" -"D:\Work\quake source\WinQuake\d_edge.c" -"D:\Work\quake source\WinQuake\d_fill.c" -"D:\Work\quake source\WinQuake\d_init.c" -"D:\Work\quake source\WinQuake\d_modech.c" -"D:\Work\quake source\WinQuake\d_part.c" -"D:\Work\quake source\WinQuake\d_polyse.c" -"D:\Work\quake source\WinQuake\d_scan.c" -"D:\Work\quake source\WinQuake\d_sky.c" -"D:\Work\quake source\WinQuake\d_sprite.c" -"D:\Work\quake source\WinQuake\d_surf.c" -"D:\Work\quake source\WinQuake\d_vars.c" -"D:\Work\quake source\WinQuake\d_zpoint.c" -"D:\Work\quake source\WinQuake\draw.c" -"D:\Work\quake source\WinQuake\host.c" -"D:\Work\quake source\WinQuake\host_cmd.c" -"D:\Work\quake source\WinQuake\in_win.c" -"D:\Work\quake source\WinQuake\keys.c" -"D:\Work\quake source\WinQuake\mathlib.c" -"D:\Work\quake source\WinQuake\menu.c" -"D:\Work\quake source\WinQuake\model.c" -"D:\Work\quake source\WinQuake\net_dgrm.c" -"D:\Work\quake source\WinQuake\net_loop.c" -"D:\Work\quake source\WinQuake\net_main.c" -"D:\Work\quake source\WinQuake\net_vcr.c" -"D:\Work\quake source\WinQuake\net_win.c" -"D:\Work\quake source\WinQuake\net_wins.c" -"D:\Work\quake source\WinQuake\net_wipx.c" -"D:\Work\quake source\WinQuake\pr_cmds.c" -"D:\Work\quake source\WinQuake\pr_edict.c" -"D:\Work\quake source\WinQuake\pr_exec.c" -"D:\Work\quake source\WinQuake\r_aclip.c" -"D:\Work\quake source\WinQuake\r_alias.c" -"D:\Work\quake source\WinQuake\r_bsp.c" -"D:\Work\quake source\WinQuake\r_draw.c" -"D:\Work\quake source\WinQuake\r_edge.c" -"D:\Work\quake source\WinQuake\r_efrag.c" -"D:\Work\quake source\WinQuake\r_light.c" -"D:\Work\quake source\WinQuake\r_main.c" -"D:\Work\quake source\WinQuake\r_misc.c" -"D:\Work\quake source\WinQuake\r_part.c" -"D:\Work\quake source\WinQuake\r_sky.c" -"D:\Work\quake source\WinQuake\r_sprite.c" -"D:\Work\quake source\WinQuake\r_surf.c" -"D:\Work\quake source\WinQuake\r_vars.c" -"D:\Work\quake source\WinQuake\sbar.c" -"D:\Work\quake source\WinQuake\screen.c" -"D:\Work\quake source\WinQuake\snd_dma.c" -"D:\Work\quake source\WinQuake\snd_mem.c" -"D:\Work\quake source\WinQuake\snd_mix.c" -"D:\Work\quake source\WinQuake\snd_win.c" -"D:\Work\quake source\WinQuake\sv_main.c" -"D:\Work\quake source\WinQuake\sv_move.c" -"D:\Work\quake source\WinQuake\sv_phys.c" -"D:\Work\quake source\WinQuake\sv_user.c" -"D:\Work\quake source\WinQuake\sys_win.c" -"D:\Work\quake source\WinQuake\vid_win.c" -"D:\Work\quake source\WinQuake\view.c" -"D:\Work\quake source\WinQuake\wad.c" -"D:\Work\quake source\WinQuake\world.c" -"D:\Work\quake source\WinQuake\zone.c" -] -Creating command line "cl.exe @C:\TEMP\RSP75C.tmp" -Creating temporary file "C:\TEMP\RSP75D.tmp" with contents -[ -.\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\Release/WinQuake.exe" -".\Release\cd_win.obj" -".\Release\chase.obj" -".\Release\cl_demo.obj" -".\Release\cl_input.obj" -".\Release\cl_main.obj" -".\Release\cl_parse.obj" -".\Release\cl_tent.obj" -".\Release\cmd.obj" -".\Release\common.obj" -".\Release\conproc.obj" -".\Release\console.obj" -".\Release\crc.obj" -".\Release\cvar.obj" -".\Release\d_edge.obj" -".\Release\d_fill.obj" -".\Release\d_init.obj" -".\Release\d_modech.obj" -".\Release\d_part.obj" -".\Release\d_polyse.obj" -".\Release\d_scan.obj" -".\Release\d_sky.obj" -".\Release\d_sprite.obj" -".\Release\d_surf.obj" -".\Release\d_vars.obj" -".\Release\d_zpoint.obj" -".\Release\draw.obj" -".\Release\host.obj" -".\Release\host_cmd.obj" -".\Release\in_win.obj" -".\Release\keys.obj" -".\Release\mathlib.obj" -".\Release\menu.obj" -".\Release\model.obj" -".\Release\net_dgrm.obj" -".\Release\net_loop.obj" -".\Release\net_main.obj" -".\Release\net_vcr.obj" -".\Release\net_win.obj" -".\Release\net_wins.obj" -".\Release\net_wipx.obj" -".\Release\pr_cmds.obj" -".\Release\pr_edict.obj" -".\Release\pr_exec.obj" -".\Release\r_aclip.obj" -".\Release\r_alias.obj" -".\Release\r_bsp.obj" -".\Release\r_draw.obj" -".\Release\r_edge.obj" -".\Release\r_efrag.obj" -".\Release\r_light.obj" -".\Release\r_main.obj" -".\Release\r_misc.obj" -".\Release\r_part.obj" -".\Release\r_sky.obj" -".\Release\r_sprite.obj" -".\Release\r_surf.obj" -".\Release\r_vars.obj" -".\Release\sbar.obj" -".\Release\screen.obj" -".\Release\snd_dma.obj" -".\Release\snd_mem.obj" -".\Release\snd_mix.obj" -".\Release\snd_win.obj" -".\Release\sv_main.obj" -".\Release\sv_move.obj" -".\Release\sv_phys.obj" -".\Release\sv_user.obj" -".\Release\sys_win.obj" -".\Release\vid_win.obj" -".\Release\view.obj" -".\Release\wad.obj" -".\Release\world.obj" -".\Release\zone.obj" -".\Release\winquake.res" -".\Release\d_draw.obj" -".\Release\d_draw16.obj" -".\Release\d_parta.obj" -".\Release\d_polysa.obj" -".\Release\d_scana.obj" -".\Release\d_spr8.obj" -".\Release\d_varsa.obj" -".\Release\math.obj" -".\Release\r_aclipa.obj" -".\Release\r_aliasa.obj" -".\Release\r_drawa.obj" -".\Release\r_edgea.obj" -".\Release\r_varsa.obj" -".\Release\snd_mixa.obj" -".\Release\surf16.obj" -".\Release\surf8.obj" -".\Release\sys_wina.obj" -".\Release\worlda.obj" -] -Creating command line "link.exe @C:\TEMP\RSP75D.tmp" -

Output Window

-Compiling resources... -Compiling... -cd_win.c -chase.c -cl_demo.c -cl_input.c -cl_main.c -cl_parse.c -cl_tent.c -cmd.c -common.c -conproc.c -console.c -crc.c -cvar.c -d_edge.c -d_fill.c -d_init.c -d_modech.c -d_part.c -d_polyse.c -d_scan.c -d_sky.c -d_sprite.c -d_surf.c -d_vars.c -d_zpoint.c -draw.c -host.c -host_cmd.c -in_win.c -keys.c -D:\Work\quake source\WinQuake\in_win.c(883) : warning C4715: 'RawValuePointer' : not all control paths return a value -mathlib.c -menu.c -model.c -net_dgrm.c -net_loop.c -net_main.c -net_vcr.c -net_win.c -net_wins.c -net_wipx.c -pr_cmds.c -pr_edict.c -pr_exec.c -r_aclip.c -r_alias.c -r_bsp.c -r_draw.c -r_edge.c -r_efrag.c -r_light.c -r_main.c -r_misc.c -r_part.c -r_sky.c -r_sprite.c -r_surf.c -r_vars.c -sbar.c -screen.c -snd_dma.c -snd_mem.c -snd_mix.c -snd_win.c -sv_main.c -sv_move.c -sv_phys.c -sv_user.c -sys_win.c -vid_win.c -view.c -D:\Work\quake source\WinQuake\vid_win.c(348) : warning C4715: 'VID_Suspend' : not all control paths return a value -wad.c -world.c -zone.c -Linking... - - - -

Results

-WinQuake.exe - 0 error(s), 2 warning(s) -
- - + + +
+

Build Log

+

+--------------------Configuration: winquake - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\TEMP\RSP74A.bat" with contents +[ +@echo off +cl /EP > .\Release\worlda.spp .\worlda.s +gas2masm\debug\gas2masm < .\Release\worlda.spp > .\Release\worlda.asm +ml /c /Cp /coff /Fo.\Release\worlda.obj /Zm /Zi .\Release\worlda.asm +del .\Release\worlda.spp +] +Creating command line "C:\TEMP\RSP74A.bat" +Creating temporary file "C:\TEMP\RSP74B.bat" with contents +[ +@echo off +cl /EP > .\Release\sys_wina.spp .\sys_wina.s +gas2masm\debug\gas2masm < .\Release\sys_wina.spp > .\Release\sys_wina.asm +ml /c /Cp /coff /Fo.\Release\sys_wina.obj /Zm /Zi .\Release\sys_wina.asm +del .\Release\sys_wina.spp +] +Creating command line "C:\TEMP\RSP74B.bat" +Creating temporary file "C:\TEMP\RSP74C.bat" with contents +[ +@echo off +cl /EP > .\Release\surf8.spp .\surf8.s +gas2masm\debug\gas2masm < .\Release\surf8.spp > .\Release\surf8.asm +ml /c /Cp /coff /Fo.\Release\surf8.obj /Zm /Zi .\Release\surf8.asm +del .\Release\surf8.spp +] +Creating command line "C:\TEMP\RSP74C.bat" +Creating temporary file "C:\TEMP\RSP74D.bat" with contents +[ +@echo off +cl /EP > .\Release\surf16.spp .\surf16.s +gas2masm\debug\gas2masm < .\Release\surf16.spp > .\Release\surf16.asm +ml /c /Cp /coff /Fo.\Release\surf16.obj /Zm /Zi .\Release\surf16.asm +del .\Release\surf16.spp +] +Creating command line "C:\TEMP\RSP74D.bat" +Creating temporary file "C:\TEMP\RSP74E.bat" with contents +[ +@echo off +cl /EP > .\Release\snd_mixa.spp .\snd_mixa.s +gas2masm\debug\gas2masm < .\Release\snd_mixa.spp > .\Release\snd_mixa.asm +ml /c /Cp /coff /Fo.\Release\snd_mixa.obj /Zm /Zi .\Release\snd_mixa.asm +del .\Release\snd_mixa.spp +] +Creating command line "C:\TEMP\RSP74E.bat" +Creating temporary file "C:\TEMP\RSP74F.bat" with contents +[ +@echo off +cl /EP > .\Release\r_varsa.spp .\r_varsa.s +gas2masm\debug\gas2masm < .\Release\r_varsa.spp > .\Release\r_varsa.asm +ml /c /Cp /coff /Fo.\Release\r_varsa.obj /Zm /Zi .\Release\r_varsa.asm +del .\Release\r_varsa.spp +] +Creating command line "C:\TEMP\RSP74F.bat" +Creating temporary file "C:\TEMP\RSP750.bat" with contents +[ +@echo off +cl /EP > .\Release\r_edgea.spp .\r_edgea.s +gas2masm\debug\gas2masm < .\Release\r_edgea.spp > .\Release\r_edgea.asm +ml /c /Cp /coff /Fo.\Release\r_edgea.obj /Zm /Zi .\Release\r_edgea.asm +del .\Release\r_edgea.spp +] +Creating command line "C:\TEMP\RSP750.bat" +Creating temporary file "C:\TEMP\RSP751.bat" with contents +[ +@echo off +cl /EP > .\Release\r_drawa.spp .\r_drawa.s +gas2masm\debug\gas2masm < .\Release\r_drawa.spp > .\Release\r_drawa.asm +ml /c /Cp /coff /Fo.\Release\r_drawa.obj /Zm /Zi .\Release\r_drawa.asm +del .\Release\r_drawa.spp +] +Creating command line "C:\TEMP\RSP751.bat" +Creating temporary file "C:\TEMP\RSP752.bat" with contents +[ +@echo off +cl /EP > .\Release\r_aliasa.spp .\r_aliasa.s +gas2masm\debug\gas2masm < .\Release\r_aliasa.spp > .\Release\r_aliasa.asm +ml /c /Cp /coff /Fo.\Release\r_aliasa.obj /Zm /Zi .\Release\r_aliasa.asm +del .\Release\r_aliasa.spp +] +Creating command line "C:\TEMP\RSP752.bat" +Creating temporary file "C:\TEMP\RSP753.bat" with contents +[ +@echo off +cl /EP > .\Release\r_aclipa.spp .\r_aclipa.s +gas2masm\debug\gas2masm < .\Release\r_aclipa.spp > .\Release\r_aclipa.asm +ml /c /Cp /coff /Fo.\Release\r_aclipa.obj /Zm /Zi .\Release\r_aclipa.asm +del .\Release\r_aclipa.spp +] +Creating command line "C:\TEMP\RSP753.bat" +Creating temporary file "C:\TEMP\RSP754.bat" with contents +[ +@echo off +cl /EP > .\Release\math.spp .\math.s +gas2masm\debug\gas2masm < .\Release\math.spp > .\Release\math.asm +ml /c /Cp /coff /Fo.\Release\math.obj /Zm /Zi .\Release\math.asm +del .\Release\math.spp +] +Creating command line "C:\TEMP\RSP754.bat" +Creating temporary file "C:\TEMP\RSP755.bat" with contents +[ +@echo off +cl /EP > .\Release\d_varsa.spp .\d_varsa.s +gas2masm\debug\gas2masm < .\Release\d_varsa.spp > .\Release\d_varsa.asm +ml /c /Cp /coff /Fo.\Release\d_varsa.obj /Zm /Zi .\Release\d_varsa.asm +del .\Release\d_varsa.spp +] +Creating command line "C:\TEMP\RSP755.bat" +Creating temporary file "C:\TEMP\RSP756.bat" with contents +[ +@echo off +cl /EP > .\Release\d_spr8.spp .\d_spr8.s +gas2masm\debug\gas2masm < .\Release\d_spr8.spp > .\Release\d_spr8.asm +ml /c /Cp /coff /Fo.\Release\d_spr8.obj /Zm /Zi .\Release\d_spr8.asm +del .\Release\d_spr8.spp +] +Creating command line "C:\TEMP\RSP756.bat" +Creating temporary file "C:\TEMP\RSP757.bat" with contents +[ +@echo off +cl /EP > .\Release\d_scana.spp .\d_scana.s +gas2masm\debug\gas2masm < .\Release\d_scana.spp > .\Release\d_scana.asm +ml /c /Cp /coff /Fo.\Release\d_scana.obj /Zm /Zi .\Release\d_scana.asm +del .\Release\d_scana.spp +] +Creating command line "C:\TEMP\RSP757.bat" +Creating temporary file "C:\TEMP\RSP758.bat" with contents +[ +@echo off +cl /EP > .\Release\d_polysa.spp .\d_polysa.s +gas2masm\debug\gas2masm < .\Release\d_polysa.spp > .\Release\d_polysa.asm +ml /c /Cp /coff /Fo.\Release\d_polysa.obj /Zm /Zi .\Release\d_polysa.asm +del .\Release\d_polysa.spp +] +Creating command line "C:\TEMP\RSP758.bat" +Creating temporary file "C:\TEMP\RSP759.bat" with contents +[ +@echo off +cl /EP > .\Release\d_parta.spp .\d_parta.s +gas2masm\debug\gas2masm < .\Release\d_parta.spp > .\Release\d_parta.asm +ml /c /Cp /coff /Fo.\Release\d_parta.obj /Zm /Zi .\Release\d_parta.asm +del .\Release\d_parta.spp +] +Creating command line "C:\TEMP\RSP759.bat" +Creating temporary file "C:\TEMP\RSP75A.bat" with contents +[ +@echo off +cl /EP > .\Release\d_draw16.spp .\d_draw16.s +gas2masm\debug\gas2masm < .\Release\d_draw16.spp > .\Release\d_draw16.asm +ml /c /Cp /coff /Fo.\Release\d_draw16.obj /Zm /Zi .\Release\d_draw16.asm +del .\Release\d_draw16.spp +] +Creating command line "C:\TEMP\RSP75A.bat" +Creating temporary file "C:\TEMP\RSP75B.bat" with contents +[ +@echo off +cl /EP > .\Release\d_draw.spp .\d_draw.s +gas2masm\debug\gas2masm < .\Release\d_draw.spp > .\Release\d_draw.asm +ml /c /Cp /coff /Fo.\Release\d_draw.obj /Zm /Zi .\Release\d_draw.asm +del .\Release\d_draw.spp +] +Creating command line "C:\TEMP\RSP75B.bat" +Creating command line "rc.exe /l 0x409 /fo".\Release/winquake.res" /d "NDEBUG" "D:\Work\quake source\WinQuake\winquake.rc"" +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +worlda.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\worlda.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +sys_wina.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\sys_wina.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +surf8.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\surf8.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +surf16.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\surf16.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +snd_mixa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\snd_mixa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +r_varsa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\r_varsa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +r_edgea.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\r_edgea.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +r_drawa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\r_drawa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +r_aliasa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\r_aliasa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +r_aclipa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\r_aclipa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +math.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\math.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_varsa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_varsa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_spr8.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_spr8.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_scana.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_scana.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_polysa.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_polysa.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_parta.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_parta.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_draw16.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_draw16.asm +mycoolbuild +Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 +Copyright (C) Microsoft Corp 1984-1998. All rights reserved. + +d_draw.s +Microsoft (R) Macro Assembler Version 6.11 +Copyright (C) Microsoft Corp 1981-1993. All rights reserved. + + Assembling: .\Release\d_draw.asm +Creating temporary file "C:\TEMP\RSP75C.tmp" with contents +[ +/nologo /G5 /ML /GX /Ox /Ot /Ow /I ".\scitech\include" /I ".\dxsdk\sdk\inc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR".\Release/" /Fp".\Release/WinQuake.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /c +"D:\Work\quake source\WinQuake\cd_win.c" +"D:\Work\quake source\WinQuake\chase.c" +"D:\Work\quake source\WinQuake\cl_demo.c" +"D:\Work\quake source\WinQuake\cl_input.c" +"D:\Work\quake source\WinQuake\cl_main.c" +"D:\Work\quake source\WinQuake\cl_parse.c" +"D:\Work\quake source\WinQuake\cl_tent.c" +"D:\Work\quake source\WinQuake\cmd.c" +"D:\Work\quake source\WinQuake\common.c" +"D:\Work\quake source\WinQuake\conproc.c" +"D:\Work\quake source\WinQuake\console.c" +"D:\Work\quake source\WinQuake\crc.c" +"D:\Work\quake source\WinQuake\cvar.c" +"D:\Work\quake source\WinQuake\d_edge.c" +"D:\Work\quake source\WinQuake\d_fill.c" +"D:\Work\quake source\WinQuake\d_init.c" +"D:\Work\quake source\WinQuake\d_modech.c" +"D:\Work\quake source\WinQuake\d_part.c" +"D:\Work\quake source\WinQuake\d_polyse.c" +"D:\Work\quake source\WinQuake\d_scan.c" +"D:\Work\quake source\WinQuake\d_sky.c" +"D:\Work\quake source\WinQuake\d_sprite.c" +"D:\Work\quake source\WinQuake\d_surf.c" +"D:\Work\quake source\WinQuake\d_vars.c" +"D:\Work\quake source\WinQuake\d_zpoint.c" +"D:\Work\quake source\WinQuake\draw.c" +"D:\Work\quake source\WinQuake\host.c" +"D:\Work\quake source\WinQuake\host_cmd.c" +"D:\Work\quake source\WinQuake\in_win.c" +"D:\Work\quake source\WinQuake\keys.c" +"D:\Work\quake source\WinQuake\mathlib.c" +"D:\Work\quake source\WinQuake\menu.c" +"D:\Work\quake source\WinQuake\model.c" +"D:\Work\quake source\WinQuake\net_dgrm.c" +"D:\Work\quake source\WinQuake\net_loop.c" +"D:\Work\quake source\WinQuake\net_main.c" +"D:\Work\quake source\WinQuake\net_vcr.c" +"D:\Work\quake source\WinQuake\net_win.c" +"D:\Work\quake source\WinQuake\net_wins.c" +"D:\Work\quake source\WinQuake\net_wipx.c" +"D:\Work\quake source\WinQuake\pr_cmds.c" +"D:\Work\quake source\WinQuake\pr_edict.c" +"D:\Work\quake source\WinQuake\pr_exec.c" +"D:\Work\quake source\WinQuake\r_aclip.c" +"D:\Work\quake source\WinQuake\r_alias.c" +"D:\Work\quake source\WinQuake\r_bsp.c" +"D:\Work\quake source\WinQuake\r_draw.c" +"D:\Work\quake source\WinQuake\r_edge.c" +"D:\Work\quake source\WinQuake\r_efrag.c" +"D:\Work\quake source\WinQuake\r_light.c" +"D:\Work\quake source\WinQuake\r_main.c" +"D:\Work\quake source\WinQuake\r_misc.c" +"D:\Work\quake source\WinQuake\r_part.c" +"D:\Work\quake source\WinQuake\r_sky.c" +"D:\Work\quake source\WinQuake\r_sprite.c" +"D:\Work\quake source\WinQuake\r_surf.c" +"D:\Work\quake source\WinQuake\r_vars.c" +"D:\Work\quake source\WinQuake\sbar.c" +"D:\Work\quake source\WinQuake\screen.c" +"D:\Work\quake source\WinQuake\snd_dma.c" +"D:\Work\quake source\WinQuake\snd_mem.c" +"D:\Work\quake source\WinQuake\snd_mix.c" +"D:\Work\quake source\WinQuake\snd_win.c" +"D:\Work\quake source\WinQuake\sv_main.c" +"D:\Work\quake source\WinQuake\sv_move.c" +"D:\Work\quake source\WinQuake\sv_phys.c" +"D:\Work\quake source\WinQuake\sv_user.c" +"D:\Work\quake source\WinQuake\sys_win.c" +"D:\Work\quake source\WinQuake\vid_win.c" +"D:\Work\quake source\WinQuake\view.c" +"D:\Work\quake source\WinQuake\wad.c" +"D:\Work\quake source\WinQuake\world.c" +"D:\Work\quake source\WinQuake\zone.c" +] +Creating command line "cl.exe @C:\TEMP\RSP75C.tmp" +Creating temporary file "C:\TEMP\RSP75D.tmp" with contents +[ +.\dxsdk\sdk\lib\dxguid.lib .\scitech\lib\win32\vc\mgllt.lib winmm.lib wsock32.lib opengl32.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:".\Release/WinQuake.exe" +".\Release\cd_win.obj" +".\Release\chase.obj" +".\Release\cl_demo.obj" +".\Release\cl_input.obj" +".\Release\cl_main.obj" +".\Release\cl_parse.obj" +".\Release\cl_tent.obj" +".\Release\cmd.obj" +".\Release\common.obj" +".\Release\conproc.obj" +".\Release\console.obj" +".\Release\crc.obj" +".\Release\cvar.obj" +".\Release\d_edge.obj" +".\Release\d_fill.obj" +".\Release\d_init.obj" +".\Release\d_modech.obj" +".\Release\d_part.obj" +".\Release\d_polyse.obj" +".\Release\d_scan.obj" +".\Release\d_sky.obj" +".\Release\d_sprite.obj" +".\Release\d_surf.obj" +".\Release\d_vars.obj" +".\Release\d_zpoint.obj" +".\Release\draw.obj" +".\Release\host.obj" +".\Release\host_cmd.obj" +".\Release\in_win.obj" +".\Release\keys.obj" +".\Release\mathlib.obj" +".\Release\menu.obj" +".\Release\model.obj" +".\Release\net_dgrm.obj" +".\Release\net_loop.obj" +".\Release\net_main.obj" +".\Release\net_vcr.obj" +".\Release\net_win.obj" +".\Release\net_wins.obj" +".\Release\net_wipx.obj" +".\Release\pr_cmds.obj" +".\Release\pr_edict.obj" +".\Release\pr_exec.obj" +".\Release\r_aclip.obj" +".\Release\r_alias.obj" +".\Release\r_bsp.obj" +".\Release\r_draw.obj" +".\Release\r_edge.obj" +".\Release\r_efrag.obj" +".\Release\r_light.obj" +".\Release\r_main.obj" +".\Release\r_misc.obj" +".\Release\r_part.obj" +".\Release\r_sky.obj" +".\Release\r_sprite.obj" +".\Release\r_surf.obj" +".\Release\r_vars.obj" +".\Release\sbar.obj" +".\Release\screen.obj" +".\Release\snd_dma.obj" +".\Release\snd_mem.obj" +".\Release\snd_mix.obj" +".\Release\snd_win.obj" +".\Release\sv_main.obj" +".\Release\sv_move.obj" +".\Release\sv_phys.obj" +".\Release\sv_user.obj" +".\Release\sys_win.obj" +".\Release\vid_win.obj" +".\Release\view.obj" +".\Release\wad.obj" +".\Release\world.obj" +".\Release\zone.obj" +".\Release\winquake.res" +".\Release\d_draw.obj" +".\Release\d_draw16.obj" +".\Release\d_parta.obj" +".\Release\d_polysa.obj" +".\Release\d_scana.obj" +".\Release\d_spr8.obj" +".\Release\d_varsa.obj" +".\Release\math.obj" +".\Release\r_aclipa.obj" +".\Release\r_aliasa.obj" +".\Release\r_drawa.obj" +".\Release\r_edgea.obj" +".\Release\r_varsa.obj" +".\Release\snd_mixa.obj" +".\Release\surf16.obj" +".\Release\surf8.obj" +".\Release\sys_wina.obj" +".\Release\worlda.obj" +] +Creating command line "link.exe @C:\TEMP\RSP75D.tmp" +

Output Window

+Compiling resources... +Compiling... +cd_win.c +chase.c +cl_demo.c +cl_input.c +cl_main.c +cl_parse.c +cl_tent.c +cmd.c +common.c +conproc.c +console.c +crc.c +cvar.c +d_edge.c +d_fill.c +d_init.c +d_modech.c +d_part.c +d_polyse.c +d_scan.c +d_sky.c +d_sprite.c +d_surf.c +d_vars.c +d_zpoint.c +draw.c +host.c +host_cmd.c +in_win.c +keys.c +D:\Work\quake source\WinQuake\in_win.c(883) : warning C4715: 'RawValuePointer' : not all control paths return a value +mathlib.c +menu.c +model.c +net_dgrm.c +net_loop.c +net_main.c +net_vcr.c +net_win.c +net_wins.c +net_wipx.c +pr_cmds.c +pr_edict.c +pr_exec.c +r_aclip.c +r_alias.c +r_bsp.c +r_draw.c +r_edge.c +r_efrag.c +r_light.c +r_main.c +r_misc.c +r_part.c +r_sky.c +r_sprite.c +r_surf.c +r_vars.c +sbar.c +screen.c +snd_dma.c +snd_mem.c +snd_mix.c +snd_win.c +sv_main.c +sv_move.c +sv_phys.c +sv_user.c +sys_win.c +vid_win.c +view.c +D:\Work\quake source\WinQuake\vid_win.c(348) : warning C4715: 'VID_Suspend' : not all control paths return a value +wad.c +world.c +zone.c +Linking... + + + +

Results

+WinQuake.exe - 0 error(s), 2 warning(s) +
+ + diff --git a/WinQuake/adivtab.h b/WinQuake/adivtab.h index 238df5c..5716906 100644 --- a/WinQuake/adivtab.h +++ b/WinQuake/adivtab.h @@ -1,1077 +1,1077 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// table of quotients and remainders for [-15...16] / [-15...16] - -// numerator = -15 -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{1, -5}, -{1, -6}, -{1, -7}, -{2, -1}, -{2, -3}, -{3, 0}, -{3, -3}, -{5, 0}, -{7, -1}, -{15, 0}, -{0, 0}, -{-15, 0}, -{-8, 1}, -{-5, 0}, -{-4, 1}, -{-3, 0}, -{-3, 3}, -{-3, 6}, -{-2, 1}, -{-2, 3}, -{-2, 5}, -{-2, 7}, -{-2, 9}, -{-2, 11}, -{-2, 13}, -{-1, 0}, -{-1, 1}, -// numerator = -14 -{0, -14}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{1, -5}, -{1, -6}, -{2, 0}, -{2, -2}, -{2, -4}, -{3, -2}, -{4, -2}, -{7, 0}, -{14, 0}, -{0, 0}, -{-14, 0}, -{-7, 0}, -{-5, 1}, -{-4, 2}, -{-3, 1}, -{-3, 4}, -{-2, 0}, -{-2, 2}, -{-2, 4}, -{-2, 6}, -{-2, 8}, -{-2, 10}, -{-2, 12}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -// numerator = -13 -{0, -13}, -{0, -13}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{1, -5}, -{1, -6}, -{2, -1}, -{2, -3}, -{3, -1}, -{4, -1}, -{6, -1}, -{13, 0}, -{0, 0}, -{-13, 0}, -{-7, 1}, -{-5, 2}, -{-4, 3}, -{-3, 2}, -{-3, 5}, -{-2, 1}, -{-2, 3}, -{-2, 5}, -{-2, 7}, -{-2, 9}, -{-2, 11}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -// numerator = -12 -{0, -12}, -{0, -12}, -{0, -12}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{1, -5}, -{2, 0}, -{2, -2}, -{3, 0}, -{4, 0}, -{6, 0}, -{12, 0}, -{0, 0}, -{-12, 0}, -{-6, 0}, -{-4, 0}, -{-3, 0}, -{-3, 3}, -{-2, 0}, -{-2, 2}, -{-2, 4}, -{-2, 6}, -{-2, 8}, -{-2, 10}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -// numerator = -11 -{0, -11}, -{0, -11}, -{0, -11}, -{0, -11}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{1, -5}, -{2, -1}, -{2, -3}, -{3, -2}, -{5, -1}, -{11, 0}, -{0, 0}, -{-11, 0}, -{-6, 1}, -{-4, 1}, -{-3, 1}, -{-3, 4}, -{-2, 1}, -{-2, 3}, -{-2, 5}, -{-2, 7}, -{-2, 9}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -// numerator = -10 -{0, -10}, -{0, -10}, -{0, -10}, -{0, -10}, -{0, -10}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{2, 0}, -{2, -2}, -{3, -1}, -{5, 0}, -{10, 0}, -{0, 0}, -{-10, 0}, -{-5, 0}, -{-4, 2}, -{-3, 2}, -{-2, 0}, -{-2, 2}, -{-2, 4}, -{-2, 6}, -{-2, 8}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -// numerator = -9 -{0, -9}, -{0, -9}, -{0, -9}, -{0, -9}, -{0, -9}, -{0, -9}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{1, -4}, -{2, -1}, -{3, 0}, -{4, -1}, -{9, 0}, -{0, 0}, -{-9, 0}, -{-5, 1}, -{-3, 0}, -{-3, 3}, -{-2, 1}, -{-2, 3}, -{-2, 5}, -{-2, 7}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -// numerator = -8 -{0, -8}, -{0, -8}, -{0, -8}, -{0, -8}, -{0, -8}, -{0, -8}, -{0, -8}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{2, 0}, -{2, -2}, -{4, 0}, -{8, 0}, -{0, 0}, -{-8, 0}, -{-4, 0}, -{-3, 1}, -{-2, 0}, -{-2, 2}, -{-2, 4}, -{-2, 6}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -// numerator = -7 -{0, -7}, -{0, -7}, -{0, -7}, -{0, -7}, -{0, -7}, -{0, -7}, -{0, -7}, -{0, -7}, -{1, 0}, -{1, -1}, -{1, -2}, -{1, -3}, -{2, -1}, -{3, -1}, -{7, 0}, -{0, 0}, -{-7, 0}, -{-4, 1}, -{-3, 2}, -{-2, 1}, -{-2, 3}, -{-2, 5}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -// numerator = -6 -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{0, -6}, -{1, 0}, -{1, -1}, -{1, -2}, -{2, 0}, -{3, 0}, -{6, 0}, -{0, 0}, -{-6, 0}, -{-3, 0}, -{-2, 0}, -{-2, 2}, -{-2, 4}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -// numerator = -5 -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{0, -5}, -{1, 0}, -{1, -1}, -{1, -2}, -{2, -1}, -{5, 0}, -{0, 0}, -{-5, 0}, -{-3, 1}, -{-2, 1}, -{-2, 3}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -{-1, 11}, -// numerator = -4 -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{0, -4}, -{1, 0}, -{1, -1}, -{2, 0}, -{4, 0}, -{0, 0}, -{-4, 0}, -{-2, 0}, -{-2, 2}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -{-1, 11}, -{-1, 12}, -// numerator = -3 -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{0, -3}, -{1, 0}, -{1, -1}, -{3, 0}, -{0, 0}, -{-3, 0}, -{-2, 1}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -{-1, 11}, -{-1, 12}, -{-1, 13}, -// numerator = -2 -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{0, -2}, -{1, 0}, -{2, 0}, -{0, 0}, -{-2, 0}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -{-1, 11}, -{-1, 12}, -{-1, 13}, -{-1, 14}, -// numerator = -1 -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{0, -1}, -{1, 0}, -{0, 0}, -{-1, 0}, -{-1, 1}, -{-1, 2}, -{-1, 3}, -{-1, 4}, -{-1, 5}, -{-1, 6}, -{-1, 7}, -{-1, 8}, -{-1, 9}, -{-1, 10}, -{-1, 11}, -{-1, 12}, -{-1, 13}, -{-1, 14}, -{-1, 15}, -// numerator = 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}, -// numerator = 1 -{-1, -14}, -{-1, -13}, -{-1, -12}, -{-1, -11}, -{-1, -10}, -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{0, 0}, -{1, 0}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -{0, 1}, -// numerator = 2 -{-1, -13}, -{-1, -12}, -{-1, -11}, -{-1, -10}, -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, 0}, -{0, 0}, -{2, 0}, -{1, 0}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -{0, 2}, -// numerator = 3 -{-1, -12}, -{-1, -11}, -{-1, -10}, -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -1}, -{-3, 0}, -{0, 0}, -{3, 0}, -{1, 1}, -{1, 0}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -{0, 3}, -// numerator = 4 -{-1, -11}, -{-1, -10}, -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -2}, -{-2, 0}, -{-4, 0}, -{0, 0}, -{4, 0}, -{2, 0}, -{1, 1}, -{1, 0}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -{0, 4}, -// numerator = 5 -{-1, -10}, -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -3}, -{-2, -1}, -{-3, -1}, -{-5, 0}, -{0, 0}, -{5, 0}, -{2, 1}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -{0, 5}, -// numerator = 6 -{-1, -9}, -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, 0}, -{-6, 0}, -{0, 0}, -{6, 0}, -{3, 0}, -{2, 0}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -{0, 6}, -// numerator = 7 -{-1, -8}, -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -5}, -{-2, -3}, -{-2, -1}, -{-3, -2}, -{-4, -1}, -{-7, 0}, -{0, 0}, -{7, 0}, -{3, 1}, -{2, 1}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -{0, 7}, -// numerator = 8 -{-1, -7}, -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -6}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, -1}, -{-4, 0}, -{-8, 0}, -{0, 0}, -{8, 0}, -{4, 0}, -{2, 2}, -{2, 0}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 8}, -{0, 8}, -{0, 8}, -{0, 8}, -{0, 8}, -{0, 8}, -{0, 8}, -{0, 8}, -// numerator = 9 -{-1, -6}, -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -7}, -{-2, -5}, -{-2, -3}, -{-2, -1}, -{-3, -3}, -{-3, 0}, -{-5, -1}, -{-9, 0}, -{0, 0}, -{9, 0}, -{4, 1}, -{3, 0}, -{2, 1}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 9}, -{0, 9}, -{0, 9}, -{0, 9}, -{0, 9}, -{0, 9}, -{0, 9}, -// numerator = 10 -{-1, -5}, -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -8}, -{-2, -6}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, -2}, -{-4, -2}, -{-5, 0}, -{-10, 0}, -{0, 0}, -{10, 0}, -{5, 0}, -{3, 1}, -{2, 2}, -{2, 0}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 10}, -{0, 10}, -{0, 10}, -{0, 10}, -{0, 10}, -{0, 10}, -// numerator = 11 -{-1, -4}, -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -9}, -{-2, -7}, -{-2, -5}, -{-2, -3}, -{-2, -1}, -{-3, -4}, -{-3, -1}, -{-4, -1}, -{-6, -1}, -{-11, 0}, -{0, 0}, -{11, 0}, -{5, 1}, -{3, 2}, -{2, 3}, -{2, 1}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 11}, -{0, 11}, -{0, 11}, -{0, 11}, -{0, 11}, -// numerator = 12 -{-1, -3}, -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -10}, -{-2, -8}, -{-2, -6}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, -3}, -{-3, 0}, -{-4, 0}, -{-6, 0}, -{-12, 0}, -{0, 0}, -{12, 0}, -{6, 0}, -{4, 0}, -{3, 0}, -{2, 2}, -{2, 0}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 12}, -{0, 12}, -{0, 12}, -{0, 12}, -// numerator = 13 -{-1, -2}, -{-1, -1}, -{-1, 0}, -{-2, -11}, -{-2, -9}, -{-2, -7}, -{-2, -5}, -{-2, -3}, -{-2, -1}, -{-3, -5}, -{-3, -2}, -{-4, -3}, -{-5, -2}, -{-7, -1}, -{-13, 0}, -{0, 0}, -{13, 0}, -{6, 1}, -{4, 1}, -{3, 1}, -{2, 3}, -{2, 1}, -{1, 6}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 13}, -{0, 13}, -{0, 13}, -// numerator = 14 -{-1, -1}, -{-1, 0}, -{-2, -12}, -{-2, -10}, -{-2, -8}, -{-2, -6}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, -4}, -{-3, -1}, -{-4, -2}, -{-5, -1}, -{-7, 0}, -{-14, 0}, -{0, 0}, -{14, 0}, -{7, 0}, -{4, 2}, -{3, 2}, -{2, 4}, -{2, 2}, -{2, 0}, -{1, 6}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 14}, -{0, 14}, -// numerator = 15 -{-1, 0}, -{-2, -13}, -{-2, -11}, -{-2, -9}, -{-2, -7}, -{-2, -5}, -{-2, -3}, -{-2, -1}, -{-3, -6}, -{-3, -3}, -{-3, 0}, -{-4, -1}, -{-5, 0}, -{-8, -1}, -{-15, 0}, -{0, 0}, -{15, 0}, -{7, 1}, -{5, 0}, -{3, 3}, -{3, 0}, -{2, 3}, -{2, 1}, -{1, 7}, -{1, 6}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, -{0, 15}, -// numerator = 16 -{-2, -14}, -{-2, -12}, -{-2, -10}, -{-2, -8}, -{-2, -6}, -{-2, -4}, -{-2, -2}, -{-2, 0}, -{-3, -5}, -{-3, -2}, -{-4, -4}, -{-4, 0}, -{-6, -2}, -{-8, 0}, -{-16, 0}, -{0, 0}, -{16, 0}, -{8, 0}, -{5, 1}, -{4, 0}, -{3, 1}, -{2, 4}, -{2, 2}, -{2, 0}, -{1, 7}, -{1, 6}, -{1, 5}, -{1, 4}, -{1, 3}, -{1, 2}, -{1, 1}, -{1, 0}, +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// table of quotients and remainders for [-15...16] / [-15...16] + +// numerator = -15 +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{1, -7}, +{2, -1}, +{2, -3}, +{3, 0}, +{3, -3}, +{5, 0}, +{7, -1}, +{15, 0}, +{0, 0}, +{-15, 0}, +{-8, 1}, +{-5, 0}, +{-4, 1}, +{-3, 0}, +{-3, 3}, +{-3, 6}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-2, 11}, +{-2, 13}, +{-1, 0}, +{-1, 1}, +// numerator = -14 +{0, -14}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{2, 0}, +{2, -2}, +{2, -4}, +{3, -2}, +{4, -2}, +{7, 0}, +{14, 0}, +{0, 0}, +{-14, 0}, +{-7, 0}, +{-5, 1}, +{-4, 2}, +{-3, 1}, +{-3, 4}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-2, 10}, +{-2, 12}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +// numerator = -13 +{0, -13}, +{0, -13}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{2, -1}, +{2, -3}, +{3, -1}, +{4, -1}, +{6, -1}, +{13, 0}, +{0, 0}, +{-13, 0}, +{-7, 1}, +{-5, 2}, +{-4, 3}, +{-3, 2}, +{-3, 5}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-2, 11}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +// numerator = -12 +{0, -12}, +{0, -12}, +{0, -12}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{2, 0}, +{2, -2}, +{3, 0}, +{4, 0}, +{6, 0}, +{12, 0}, +{0, 0}, +{-12, 0}, +{-6, 0}, +{-4, 0}, +{-3, 0}, +{-3, 3}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-2, 10}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +// numerator = -11 +{0, -11}, +{0, -11}, +{0, -11}, +{0, -11}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{2, -1}, +{2, -3}, +{3, -2}, +{5, -1}, +{11, 0}, +{0, 0}, +{-11, 0}, +{-6, 1}, +{-4, 1}, +{-3, 1}, +{-3, 4}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +// numerator = -10 +{0, -10}, +{0, -10}, +{0, -10}, +{0, -10}, +{0, -10}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{2, 0}, +{2, -2}, +{3, -1}, +{5, 0}, +{10, 0}, +{0, 0}, +{-10, 0}, +{-5, 0}, +{-4, 2}, +{-3, 2}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +// numerator = -9 +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{2, -1}, +{3, 0}, +{4, -1}, +{9, 0}, +{0, 0}, +{-9, 0}, +{-5, 1}, +{-3, 0}, +{-3, 3}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +// numerator = -8 +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{2, 0}, +{2, -2}, +{4, 0}, +{8, 0}, +{0, 0}, +{-8, 0}, +{-4, 0}, +{-3, 1}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +// numerator = -7 +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{2, -1}, +{3, -1}, +{7, 0}, +{0, 0}, +{-7, 0}, +{-4, 1}, +{-3, 2}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +// numerator = -6 +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{1, 0}, +{1, -1}, +{1, -2}, +{2, 0}, +{3, 0}, +{6, 0}, +{0, 0}, +{-6, 0}, +{-3, 0}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +// numerator = -5 +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{1, 0}, +{1, -1}, +{1, -2}, +{2, -1}, +{5, 0}, +{0, 0}, +{-5, 0}, +{-3, 1}, +{-2, 1}, +{-2, 3}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +// numerator = -4 +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{1, 0}, +{1, -1}, +{2, 0}, +{4, 0}, +{0, 0}, +{-4, 0}, +{-2, 0}, +{-2, 2}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +// numerator = -3 +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{1, 0}, +{1, -1}, +{3, 0}, +{0, 0}, +{-3, 0}, +{-2, 1}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +// numerator = -2 +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{1, 0}, +{2, 0}, +{0, 0}, +{-2, 0}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +{-1, 14}, +// numerator = -1 +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{1, 0}, +{0, 0}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +{-1, 14}, +{-1, 15}, +// numerator = 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}, +// numerator = 1 +{-1, -14}, +{-1, -13}, +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{0, 0}, +{1, 0}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +// numerator = 2 +{-1, -13}, +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, 0}, +{0, 0}, +{2, 0}, +{1, 0}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +// numerator = 3 +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -1}, +{-3, 0}, +{0, 0}, +{3, 0}, +{1, 1}, +{1, 0}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +// numerator = 4 +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -2}, +{-2, 0}, +{-4, 0}, +{0, 0}, +{4, 0}, +{2, 0}, +{1, 1}, +{1, 0}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +// numerator = 5 +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -3}, +{-2, -1}, +{-3, -1}, +{-5, 0}, +{0, 0}, +{5, 0}, +{2, 1}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +// numerator = 6 +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, 0}, +{-6, 0}, +{0, 0}, +{6, 0}, +{3, 0}, +{2, 0}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +// numerator = 7 +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -2}, +{-4, -1}, +{-7, 0}, +{0, 0}, +{7, 0}, +{3, 1}, +{2, 1}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +// numerator = 8 +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -1}, +{-4, 0}, +{-8, 0}, +{0, 0}, +{8, 0}, +{4, 0}, +{2, 2}, +{2, 0}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +// numerator = 9 +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -3}, +{-3, 0}, +{-5, -1}, +{-9, 0}, +{0, 0}, +{9, 0}, +{4, 1}, +{3, 0}, +{2, 1}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +// numerator = 10 +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -2}, +{-4, -2}, +{-5, 0}, +{-10, 0}, +{0, 0}, +{10, 0}, +{5, 0}, +{3, 1}, +{2, 2}, +{2, 0}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +// numerator = 11 +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -4}, +{-3, -1}, +{-4, -1}, +{-6, -1}, +{-11, 0}, +{0, 0}, +{11, 0}, +{5, 1}, +{3, 2}, +{2, 3}, +{2, 1}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 11}, +{0, 11}, +{0, 11}, +{0, 11}, +{0, 11}, +// numerator = 12 +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -3}, +{-3, 0}, +{-4, 0}, +{-6, 0}, +{-12, 0}, +{0, 0}, +{12, 0}, +{6, 0}, +{4, 0}, +{3, 0}, +{2, 2}, +{2, 0}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 12}, +{0, 12}, +{0, 12}, +{0, 12}, +// numerator = 13 +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -11}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -5}, +{-3, -2}, +{-4, -3}, +{-5, -2}, +{-7, -1}, +{-13, 0}, +{0, 0}, +{13, 0}, +{6, 1}, +{4, 1}, +{3, 1}, +{2, 3}, +{2, 1}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 13}, +{0, 13}, +{0, 13}, +// numerator = 14 +{-1, -1}, +{-1, 0}, +{-2, -12}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -4}, +{-3, -1}, +{-4, -2}, +{-5, -1}, +{-7, 0}, +{-14, 0}, +{0, 0}, +{14, 0}, +{7, 0}, +{4, 2}, +{3, 2}, +{2, 4}, +{2, 2}, +{2, 0}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 14}, +{0, 14}, +// numerator = 15 +{-1, 0}, +{-2, -13}, +{-2, -11}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -6}, +{-3, -3}, +{-3, 0}, +{-4, -1}, +{-5, 0}, +{-8, -1}, +{-15, 0}, +{0, 0}, +{15, 0}, +{7, 1}, +{5, 0}, +{3, 3}, +{3, 0}, +{2, 3}, +{2, 1}, +{1, 7}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 15}, +// numerator = 16 +{-2, -14}, +{-2, -12}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -5}, +{-3, -2}, +{-4, -4}, +{-4, 0}, +{-6, -2}, +{-8, 0}, +{-16, 0}, +{0, 0}, +{16, 0}, +{8, 0}, +{5, 1}, +{4, 0}, +{3, 1}, +{2, 4}, +{2, 2}, +{2, 0}, +{1, 7}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, diff --git a/WinQuake/anorm_dots.h b/WinQuake/anorm_dots.h index 2845fa2..2abea60 100644 --- a/WinQuake/anorm_dots.h +++ b/WinQuake/anorm_dots.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ { {1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, {1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, diff --git a/WinQuake/anorms.h b/WinQuake/anorms.h index 11a9007..8804226 100644 --- a/WinQuake/anorms.h +++ b/WinQuake/anorms.h @@ -1,181 +1,181 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -{-0.525731, 0.000000, 0.850651}, -{-0.442863, 0.238856, 0.864188}, -{-0.295242, 0.000000, 0.955423}, -{-0.309017, 0.500000, 0.809017}, -{-0.162460, 0.262866, 0.951056}, -{0.000000, 0.000000, 1.000000}, -{0.000000, 0.850651, 0.525731}, -{-0.147621, 0.716567, 0.681718}, -{0.147621, 0.716567, 0.681718}, -{0.000000, 0.525731, 0.850651}, -{0.309017, 0.500000, 0.809017}, -{0.525731, 0.000000, 0.850651}, -{0.295242, 0.000000, 0.955423}, -{0.442863, 0.238856, 0.864188}, -{0.162460, 0.262866, 0.951056}, -{-0.681718, 0.147621, 0.716567}, -{-0.809017, 0.309017, 0.500000}, -{-0.587785, 0.425325, 0.688191}, -{-0.850651, 0.525731, 0.000000}, -{-0.864188, 0.442863, 0.238856}, -{-0.716567, 0.681718, 0.147621}, -{-0.688191, 0.587785, 0.425325}, -{-0.500000, 0.809017, 0.309017}, -{-0.238856, 0.864188, 0.442863}, -{-0.425325, 0.688191, 0.587785}, -{-0.716567, 0.681718, -0.147621}, -{-0.500000, 0.809017, -0.309017}, -{-0.525731, 0.850651, 0.000000}, -{0.000000, 0.850651, -0.525731}, -{-0.238856, 0.864188, -0.442863}, -{0.000000, 0.955423, -0.295242}, -{-0.262866, 0.951056, -0.162460}, -{0.000000, 1.000000, 0.000000}, -{0.000000, 0.955423, 0.295242}, -{-0.262866, 0.951056, 0.162460}, -{0.238856, 0.864188, 0.442863}, -{0.262866, 0.951056, 0.162460}, -{0.500000, 0.809017, 0.309017}, -{0.238856, 0.864188, -0.442863}, -{0.262866, 0.951056, -0.162460}, -{0.500000, 0.809017, -0.309017}, -{0.850651, 0.525731, 0.000000}, -{0.716567, 0.681718, 0.147621}, -{0.716567, 0.681718, -0.147621}, -{0.525731, 0.850651, 0.000000}, -{0.425325, 0.688191, 0.587785}, -{0.864188, 0.442863, 0.238856}, -{0.688191, 0.587785, 0.425325}, -{0.809017, 0.309017, 0.500000}, -{0.681718, 0.147621, 0.716567}, -{0.587785, 0.425325, 0.688191}, -{0.955423, 0.295242, 0.000000}, -{1.000000, 0.000000, 0.000000}, -{0.951056, 0.162460, 0.262866}, -{0.850651, -0.525731, 0.000000}, -{0.955423, -0.295242, 0.000000}, -{0.864188, -0.442863, 0.238856}, -{0.951056, -0.162460, 0.262866}, -{0.809017, -0.309017, 0.500000}, -{0.681718, -0.147621, 0.716567}, -{0.850651, 0.000000, 0.525731}, -{0.864188, 0.442863, -0.238856}, -{0.809017, 0.309017, -0.500000}, -{0.951056, 0.162460, -0.262866}, -{0.525731, 0.000000, -0.850651}, -{0.681718, 0.147621, -0.716567}, -{0.681718, -0.147621, -0.716567}, -{0.850651, 0.000000, -0.525731}, -{0.809017, -0.309017, -0.500000}, -{0.864188, -0.442863, -0.238856}, -{0.951056, -0.162460, -0.262866}, -{0.147621, 0.716567, -0.681718}, -{0.309017, 0.500000, -0.809017}, -{0.425325, 0.688191, -0.587785}, -{0.442863, 0.238856, -0.864188}, -{0.587785, 0.425325, -0.688191}, -{0.688191, 0.587785, -0.425325}, -{-0.147621, 0.716567, -0.681718}, -{-0.309017, 0.500000, -0.809017}, -{0.000000, 0.525731, -0.850651}, -{-0.525731, 0.000000, -0.850651}, -{-0.442863, 0.238856, -0.864188}, -{-0.295242, 0.000000, -0.955423}, -{-0.162460, 0.262866, -0.951056}, -{0.000000, 0.000000, -1.000000}, -{0.295242, 0.000000, -0.955423}, -{0.162460, 0.262866, -0.951056}, -{-0.442863, -0.238856, -0.864188}, -{-0.309017, -0.500000, -0.809017}, -{-0.162460, -0.262866, -0.951056}, -{0.000000, -0.850651, -0.525731}, -{-0.147621, -0.716567, -0.681718}, -{0.147621, -0.716567, -0.681718}, -{0.000000, -0.525731, -0.850651}, -{0.309017, -0.500000, -0.809017}, -{0.442863, -0.238856, -0.864188}, -{0.162460, -0.262866, -0.951056}, -{0.238856, -0.864188, -0.442863}, -{0.500000, -0.809017, -0.309017}, -{0.425325, -0.688191, -0.587785}, -{0.716567, -0.681718, -0.147621}, -{0.688191, -0.587785, -0.425325}, -{0.587785, -0.425325, -0.688191}, -{0.000000, -0.955423, -0.295242}, -{0.000000, -1.000000, 0.000000}, -{0.262866, -0.951056, -0.162460}, -{0.000000, -0.850651, 0.525731}, -{0.000000, -0.955423, 0.295242}, -{0.238856, -0.864188, 0.442863}, -{0.262866, -0.951056, 0.162460}, -{0.500000, -0.809017, 0.309017}, -{0.716567, -0.681718, 0.147621}, -{0.525731, -0.850651, 0.000000}, -{-0.238856, -0.864188, -0.442863}, -{-0.500000, -0.809017, -0.309017}, -{-0.262866, -0.951056, -0.162460}, -{-0.850651, -0.525731, 0.000000}, -{-0.716567, -0.681718, -0.147621}, -{-0.716567, -0.681718, 0.147621}, -{-0.525731, -0.850651, 0.000000}, -{-0.500000, -0.809017, 0.309017}, -{-0.238856, -0.864188, 0.442863}, -{-0.262866, -0.951056, 0.162460}, -{-0.864188, -0.442863, 0.238856}, -{-0.809017, -0.309017, 0.500000}, -{-0.688191, -0.587785, 0.425325}, -{-0.681718, -0.147621, 0.716567}, -{-0.442863, -0.238856, 0.864188}, -{-0.587785, -0.425325, 0.688191}, -{-0.309017, -0.500000, 0.809017}, -{-0.147621, -0.716567, 0.681718}, -{-0.425325, -0.688191, 0.587785}, -{-0.162460, -0.262866, 0.951056}, -{0.442863, -0.238856, 0.864188}, -{0.162460, -0.262866, 0.951056}, -{0.309017, -0.500000, 0.809017}, -{0.147621, -0.716567, 0.681718}, -{0.000000, -0.525731, 0.850651}, -{0.425325, -0.688191, 0.587785}, -{0.587785, -0.425325, 0.688191}, -{0.688191, -0.587785, 0.425325}, -{-0.955423, 0.295242, 0.000000}, -{-0.951056, 0.162460, 0.262866}, -{-1.000000, 0.000000, 0.000000}, -{-0.850651, 0.000000, 0.525731}, -{-0.955423, -0.295242, 0.000000}, -{-0.951056, -0.162460, 0.262866}, -{-0.864188, 0.442863, -0.238856}, -{-0.951056, 0.162460, -0.262866}, -{-0.809017, 0.309017, -0.500000}, -{-0.864188, -0.442863, -0.238856}, -{-0.951056, -0.162460, -0.262866}, -{-0.809017, -0.309017, -0.500000}, -{-0.681718, 0.147621, -0.716567}, -{-0.681718, -0.147621, -0.716567}, -{-0.850651, 0.000000, -0.525731}, -{-0.688191, 0.587785, -0.425325}, -{-0.587785, 0.425325, -0.688191}, -{-0.425325, 0.688191, -0.587785}, -{-0.425325, -0.688191, -0.587785}, -{-0.587785, -0.425325, -0.688191}, -{-0.688191, -0.587785, -0.425325}, +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +{-0.525731, 0.000000, 0.850651}, +{-0.442863, 0.238856, 0.864188}, +{-0.295242, 0.000000, 0.955423}, +{-0.309017, 0.500000, 0.809017}, +{-0.162460, 0.262866, 0.951056}, +{0.000000, 0.000000, 1.000000}, +{0.000000, 0.850651, 0.525731}, +{-0.147621, 0.716567, 0.681718}, +{0.147621, 0.716567, 0.681718}, +{0.000000, 0.525731, 0.850651}, +{0.309017, 0.500000, 0.809017}, +{0.525731, 0.000000, 0.850651}, +{0.295242, 0.000000, 0.955423}, +{0.442863, 0.238856, 0.864188}, +{0.162460, 0.262866, 0.951056}, +{-0.681718, 0.147621, 0.716567}, +{-0.809017, 0.309017, 0.500000}, +{-0.587785, 0.425325, 0.688191}, +{-0.850651, 0.525731, 0.000000}, +{-0.864188, 0.442863, 0.238856}, +{-0.716567, 0.681718, 0.147621}, +{-0.688191, 0.587785, 0.425325}, +{-0.500000, 0.809017, 0.309017}, +{-0.238856, 0.864188, 0.442863}, +{-0.425325, 0.688191, 0.587785}, +{-0.716567, 0.681718, -0.147621}, +{-0.500000, 0.809017, -0.309017}, +{-0.525731, 0.850651, 0.000000}, +{0.000000, 0.850651, -0.525731}, +{-0.238856, 0.864188, -0.442863}, +{0.000000, 0.955423, -0.295242}, +{-0.262866, 0.951056, -0.162460}, +{0.000000, 1.000000, 0.000000}, +{0.000000, 0.955423, 0.295242}, +{-0.262866, 0.951056, 0.162460}, +{0.238856, 0.864188, 0.442863}, +{0.262866, 0.951056, 0.162460}, +{0.500000, 0.809017, 0.309017}, +{0.238856, 0.864188, -0.442863}, +{0.262866, 0.951056, -0.162460}, +{0.500000, 0.809017, -0.309017}, +{0.850651, 0.525731, 0.000000}, +{0.716567, 0.681718, 0.147621}, +{0.716567, 0.681718, -0.147621}, +{0.525731, 0.850651, 0.000000}, +{0.425325, 0.688191, 0.587785}, +{0.864188, 0.442863, 0.238856}, +{0.688191, 0.587785, 0.425325}, +{0.809017, 0.309017, 0.500000}, +{0.681718, 0.147621, 0.716567}, +{0.587785, 0.425325, 0.688191}, +{0.955423, 0.295242, 0.000000}, +{1.000000, 0.000000, 0.000000}, +{0.951056, 0.162460, 0.262866}, +{0.850651, -0.525731, 0.000000}, +{0.955423, -0.295242, 0.000000}, +{0.864188, -0.442863, 0.238856}, +{0.951056, -0.162460, 0.262866}, +{0.809017, -0.309017, 0.500000}, +{0.681718, -0.147621, 0.716567}, +{0.850651, 0.000000, 0.525731}, +{0.864188, 0.442863, -0.238856}, +{0.809017, 0.309017, -0.500000}, +{0.951056, 0.162460, -0.262866}, +{0.525731, 0.000000, -0.850651}, +{0.681718, 0.147621, -0.716567}, +{0.681718, -0.147621, -0.716567}, +{0.850651, 0.000000, -0.525731}, +{0.809017, -0.309017, -0.500000}, +{0.864188, -0.442863, -0.238856}, +{0.951056, -0.162460, -0.262866}, +{0.147621, 0.716567, -0.681718}, +{0.309017, 0.500000, -0.809017}, +{0.425325, 0.688191, -0.587785}, +{0.442863, 0.238856, -0.864188}, +{0.587785, 0.425325, -0.688191}, +{0.688191, 0.587785, -0.425325}, +{-0.147621, 0.716567, -0.681718}, +{-0.309017, 0.500000, -0.809017}, +{0.000000, 0.525731, -0.850651}, +{-0.525731, 0.000000, -0.850651}, +{-0.442863, 0.238856, -0.864188}, +{-0.295242, 0.000000, -0.955423}, +{-0.162460, 0.262866, -0.951056}, +{0.000000, 0.000000, -1.000000}, +{0.295242, 0.000000, -0.955423}, +{0.162460, 0.262866, -0.951056}, +{-0.442863, -0.238856, -0.864188}, +{-0.309017, -0.500000, -0.809017}, +{-0.162460, -0.262866, -0.951056}, +{0.000000, -0.850651, -0.525731}, +{-0.147621, -0.716567, -0.681718}, +{0.147621, -0.716567, -0.681718}, +{0.000000, -0.525731, -0.850651}, +{0.309017, -0.500000, -0.809017}, +{0.442863, -0.238856, -0.864188}, +{0.162460, -0.262866, -0.951056}, +{0.238856, -0.864188, -0.442863}, +{0.500000, -0.809017, -0.309017}, +{0.425325, -0.688191, -0.587785}, +{0.716567, -0.681718, -0.147621}, +{0.688191, -0.587785, -0.425325}, +{0.587785, -0.425325, -0.688191}, +{0.000000, -0.955423, -0.295242}, +{0.000000, -1.000000, 0.000000}, +{0.262866, -0.951056, -0.162460}, +{0.000000, -0.850651, 0.525731}, +{0.000000, -0.955423, 0.295242}, +{0.238856, -0.864188, 0.442863}, +{0.262866, -0.951056, 0.162460}, +{0.500000, -0.809017, 0.309017}, +{0.716567, -0.681718, 0.147621}, +{0.525731, -0.850651, 0.000000}, +{-0.238856, -0.864188, -0.442863}, +{-0.500000, -0.809017, -0.309017}, +{-0.262866, -0.951056, -0.162460}, +{-0.850651, -0.525731, 0.000000}, +{-0.716567, -0.681718, -0.147621}, +{-0.716567, -0.681718, 0.147621}, +{-0.525731, -0.850651, 0.000000}, +{-0.500000, -0.809017, 0.309017}, +{-0.238856, -0.864188, 0.442863}, +{-0.262866, -0.951056, 0.162460}, +{-0.864188, -0.442863, 0.238856}, +{-0.809017, -0.309017, 0.500000}, +{-0.688191, -0.587785, 0.425325}, +{-0.681718, -0.147621, 0.716567}, +{-0.442863, -0.238856, 0.864188}, +{-0.587785, -0.425325, 0.688191}, +{-0.309017, -0.500000, 0.809017}, +{-0.147621, -0.716567, 0.681718}, +{-0.425325, -0.688191, 0.587785}, +{-0.162460, -0.262866, 0.951056}, +{0.442863, -0.238856, 0.864188}, +{0.162460, -0.262866, 0.951056}, +{0.309017, -0.500000, 0.809017}, +{0.147621, -0.716567, 0.681718}, +{0.000000, -0.525731, 0.850651}, +{0.425325, -0.688191, 0.587785}, +{0.587785, -0.425325, 0.688191}, +{0.688191, -0.587785, 0.425325}, +{-0.955423, 0.295242, 0.000000}, +{-0.951056, 0.162460, 0.262866}, +{-1.000000, 0.000000, 0.000000}, +{-0.850651, 0.000000, 0.525731}, +{-0.955423, -0.295242, 0.000000}, +{-0.951056, -0.162460, 0.262866}, +{-0.864188, 0.442863, -0.238856}, +{-0.951056, 0.162460, -0.262866}, +{-0.809017, 0.309017, -0.500000}, +{-0.864188, -0.442863, -0.238856}, +{-0.951056, -0.162460, -0.262866}, +{-0.809017, -0.309017, -0.500000}, +{-0.681718, 0.147621, -0.716567}, +{-0.681718, -0.147621, -0.716567}, +{-0.850651, 0.000000, -0.525731}, +{-0.688191, 0.587785, -0.425325}, +{-0.587785, 0.425325, -0.688191}, +{-0.425325, 0.688191, -0.587785}, +{-0.425325, -0.688191, -0.587785}, +{-0.587785, -0.425325, -0.688191}, +{-0.688191, -0.587785, -0.425325}, diff --git a/WinQuake/asm_draw.h b/WinQuake/asm_draw.h index 5534ab6..212762a 100644 --- a/WinQuake/asm_draw.h +++ b/WinQuake/asm_draw.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // asm_draw.h // diff --git a/WinQuake/asm_i386.h b/WinQuake/asm_i386.h index 03dc2aa..c7c7ca9 100644 --- a/WinQuake/asm_i386.h +++ b/WinQuake/asm_i386.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #ifndef __ASM_I386__ #define __ASM_I386__ diff --git a/WinQuake/block16.h b/WinQuake/block16.h index 96f222e..facc932 100644 --- a/WinQuake/block16.h +++ b/WinQuake/block16.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ LEnter16_16: movb (%esi),%al movb (%esi,%ebx,),%cl diff --git a/WinQuake/block8.h b/WinQuake/block8.h index eb9b03c..1d916bb 100644 --- a/WinQuake/block8.h +++ b/WinQuake/block8.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ LEnter16_8: movb (%esi),%al movb (%esi,%ebx,),%cl diff --git a/WinQuake/bspfile.h b/WinQuake/bspfile.h index 3089026..91499c8 100644 --- a/WinQuake/bspfile.h +++ b/WinQuake/bspfile.h @@ -1,324 +1,324 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - - -// upper design bounds - -#define MAX_MAP_HULLS 4 - -#define MAX_MAP_MODELS 256 -#define MAX_MAP_BRUSHES 4096 -#define MAX_MAP_ENTITIES 1024 -#define MAX_MAP_ENTSTRING 65536 - -#define MAX_MAP_PLANES 32767 -#define MAX_MAP_NODES 32767 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 32767 // -#define MAX_MAP_LEAFS 8192 -#define MAX_MAP_VERTS 65535 -#define MAX_MAP_FACES 65535 -#define MAX_MAP_MARKSURFACES 65535 -#define MAX_MAP_TEXINFO 4096 -#define MAX_MAP_EDGES 256000 -#define MAX_MAP_SURFEDGES 512000 -#define MAX_MAP_TEXTURES 512 -#define MAX_MAP_MIPTEX 0x200000 -#define MAX_MAP_LIGHTING 0x100000 -#define MAX_MAP_VISIBILITY 0x100000 - -#define MAX_MAP_PORTALS 65536 - -// key / value pair sizes - -#define MAX_KEY 32 -#define MAX_VALUE 1024 - -//============================================================================= - - -#define BSPVERSION 29 -#define TOOLVERSION 2 - -typedef struct -{ - int fileofs, filelen; -} lump_t; - -#define LUMP_ENTITIES 0 -#define LUMP_PLANES 1 -#define LUMP_TEXTURES 2 -#define LUMP_VERTEXES 3 -#define LUMP_VISIBILITY 4 -#define LUMP_NODES 5 -#define LUMP_TEXINFO 6 -#define LUMP_FACES 7 -#define LUMP_LIGHTING 8 -#define LUMP_CLIPNODES 9 -#define LUMP_LEAFS 10 -#define LUMP_MARKSURFACES 11 -#define LUMP_EDGES 12 -#define LUMP_SURFEDGES 13 -#define LUMP_MODELS 14 - -#define HEADER_LUMPS 15 - -typedef struct -{ - float mins[3], maxs[3]; - float origin[3]; - int headnode[MAX_MAP_HULLS]; - int visleafs; // not including the solid leaf 0 - int firstface, numfaces; -} dmodel_t; - -typedef struct -{ - int version; - lump_t lumps[HEADER_LUMPS]; -} dheader_t; - -typedef struct -{ - int nummiptex; - int dataofs[4]; // [nummiptex] -} dmiptexlump_t; - -#define MIPLEVELS 4 -typedef struct miptex_s -{ - char name[16]; - unsigned width, height; - unsigned offsets[MIPLEVELS]; // four mip maps stored -} miptex_t; - - -typedef struct -{ - float point[3]; -} dvertex_t; - - -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 - -// 3-5 are non-axial planes snapped to the nearest -#define PLANE_ANYX 3 -#define PLANE_ANYY 4 -#define PLANE_ANYZ 5 - -typedef struct -{ - float normal[3]; - float dist; - int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate -} dplane_t; - - - -#define CONTENTS_EMPTY -1 -#define CONTENTS_SOLID -2 -#define CONTENTS_WATER -3 -#define CONTENTS_SLIME -4 -#define CONTENTS_LAVA -5 -#define CONTENTS_SKY -6 -#define CONTENTS_ORIGIN -7 // removed at csg time -#define CONTENTS_CLIP -8 // changed to contents_solid - -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 -#define CONTENTS_CURRENT_180 -11 -#define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 -#define CONTENTS_CURRENT_DOWN -14 - - -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct -{ - int planenum; - short children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for sphere culling - short maxs[3]; - unsigned short firstface; - unsigned short numfaces; // counting both sides -} dnode_t; - -typedef struct -{ - int planenum; - short children[2]; // negative numbers are contents -} dclipnode_t; - - -typedef struct texinfo_s -{ - float vecs[2][4]; // [s/t][xyz offset] - int miptex; - int flags; -} texinfo_t; -#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision - -// note that edge 0 is never used, because negative edge nums are used for -// counterclockwise use of the edge in a face -typedef struct -{ - unsigned short v[2]; // vertex numbers -} dedge_t; - -#define MAXLIGHTMAPS 4 -typedef struct -{ - short planenum; - short side; - - int firstedge; // we must support > 64k edges - short numedges; - short texinfo; - -// lighting info - byte styles[MAXLIGHTMAPS]; - int lightofs; // start of [numstyles*surfsize] samples -} dface_t; - - - -#define AMBIENT_WATER 0 -#define AMBIENT_SKY 1 -#define AMBIENT_SLIME 2 -#define AMBIENT_LAVA 3 - -#define NUM_AMBIENTS 4 // automatic ambient sounds - -// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas -// all other leafs need visibility info -typedef struct -{ - int contents; - int visofs; // -1 = no visibility info - - short mins[3]; // for frustum culling - short maxs[3]; - - unsigned short firstmarksurface; - unsigned short nummarksurfaces; - - byte ambient_level[NUM_AMBIENTS]; -} dleaf_t; - - -//============================================================================ - -#ifndef QUAKE_GAME - -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - - -// the utilities get to be lazy and just use large static arrays - -extern int nummodels; -extern dmodel_t dmodels[MAX_MAP_MODELS]; - -extern int visdatasize; -extern byte dvisdata[MAX_MAP_VISIBILITY]; - -extern int lightdatasize; -extern byte dlightdata[MAX_MAP_LIGHTING]; - -extern int texdatasize; -extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) - -extern int entdatasize; -extern char dentdata[MAX_MAP_ENTSTRING]; - -extern int numleafs; -extern dleaf_t dleafs[MAX_MAP_LEAFS]; - -extern int numplanes; -extern dplane_t dplanes[MAX_MAP_PLANES]; - -extern int numvertexes; -extern dvertex_t dvertexes[MAX_MAP_VERTS]; - -extern int numnodes; -extern dnode_t dnodes[MAX_MAP_NODES]; - -extern int numtexinfo; -extern texinfo_t texinfo[MAX_MAP_TEXINFO]; - -extern int numfaces; -extern dface_t dfaces[MAX_MAP_FACES]; - -extern int numclipnodes; -extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; - -extern int numedges; -extern dedge_t dedges[MAX_MAP_EDGES]; - -extern int nummarksurfaces; -extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; - -extern int numsurfedges; -extern int dsurfedges[MAX_MAP_SURFEDGES]; - - -void DecompressVis (byte *in, byte *decompressed); -int CompressVis (byte *vis, byte *dest); - -void LoadBSPFile (char *filename); -void WriteBSPFile (char *filename); -void PrintBSPFileSizes (void); - -//=============== - - -typedef struct epair_s -{ - struct epair_s *next; - char *key; - char *value; -} epair_t; - -typedef struct -{ - vec3_t origin; - int firstbrush; - int numbrushes; - epair_t *epairs; -} entity_t; - -extern int num_entities; -extern entity_t entities[MAX_MAP_ENTITIES]; - -void ParseEntities (void); -void UnparseEntities (void); - -void SetKeyValue (entity_t *ent, char *key, char *value); -char *ValueForKey (entity_t *ent, char *key); -// will return "" if not present - -vec_t FloatForKey (entity_t *ent, char *key); -void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); - -epair_t *ParseEpair (void); - -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + +// upper design bounds + +#define MAX_MAP_HULLS 4 + +#define MAX_MAP_MODELS 256 +#define MAX_MAP_BRUSHES 4096 +#define MAX_MAP_ENTITIES 1024 +#define MAX_MAP_ENTSTRING 65536 + +#define MAX_MAP_PLANES 32767 +#define MAX_MAP_NODES 32767 // because negative shorts are contents +#define MAX_MAP_CLIPNODES 32767 // +#define MAX_MAP_LEAFS 8192 +#define MAX_MAP_VERTS 65535 +#define MAX_MAP_FACES 65535 +#define MAX_MAP_MARKSURFACES 65535 +#define MAX_MAP_TEXINFO 4096 +#define MAX_MAP_EDGES 256000 +#define MAX_MAP_SURFEDGES 512000 +#define MAX_MAP_TEXTURES 512 +#define MAX_MAP_MIPTEX 0x200000 +#define MAX_MAP_LIGHTING 0x100000 +#define MAX_MAP_VISIBILITY 0x100000 + +#define MAX_MAP_PORTALS 65536 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 1024 + +//============================================================================= + + +#define BSPVERSION 29 +#define TOOLVERSION 2 + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_TEXTURES 2 +#define LUMP_VERTEXES 3 +#define LUMP_VISIBILITY 4 +#define LUMP_NODES 5 +#define LUMP_TEXINFO 6 +#define LUMP_FACES 7 +#define LUMP_LIGHTING 8 +#define LUMP_CLIPNODES 9 +#define LUMP_LEAFS 10 +#define LUMP_MARKSURFACES 11 +#define LUMP_EDGES 12 +#define LUMP_SURFEDGES 13 +#define LUMP_MODELS 14 + +#define HEADER_LUMPS 15 + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; + int headnode[MAX_MAP_HULLS]; + int visleafs; // not including the solid leaf 0 + int firstface, numfaces; +} dmodel_t; + +typedef struct +{ + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + int nummiptex; + int dataofs[4]; // [nummiptex] +} dmiptexlump_t; + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[16]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored +} miptex_t; + + +typedef struct +{ + float point[3]; +} dvertex_t; + + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + + + +#define CONTENTS_EMPTY -1 +#define CONTENTS_SOLID -2 +#define CONTENTS_WATER -3 +#define CONTENTS_SLIME -4 +#define CONTENTS_LAVA -5 +#define CONTENTS_SKY -6 +#define CONTENTS_ORIGIN -7 // removed at csg time +#define CONTENTS_CLIP -8 // changed to contents_solid + +#define CONTENTS_CURRENT_0 -9 +#define CONTENTS_CURRENT_90 -10 +#define CONTENTS_CURRENT_180 -11 +#define CONTENTS_CURRENT_270 -12 +#define CONTENTS_CURRENT_UP -13 +#define CONTENTS_CURRENT_DOWN -14 + + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + int planenum; + short children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for sphere culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + +typedef struct +{ + int planenum; + short children[2]; // negative numbers are contents +} dclipnode_t; + + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int miptex; + int flags; +} texinfo_t; +#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 +typedef struct +{ + short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + + + +#define AMBIENT_WATER 0 +#define AMBIENT_SKY 1 +#define AMBIENT_SLIME 2 +#define AMBIENT_LAVA 3 + +#define NUM_AMBIENTS 4 // automatic ambient sounds + +// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas +// all other leafs need visibility info +typedef struct +{ + int contents; + int visofs; // -1 = no visibility info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstmarksurface; + unsigned short nummarksurfaces; + + byte ambient_level[NUM_AMBIENTS]; +} dleaf_t; + + +//============================================================================ + +#ifndef QUAKE_GAME + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + + +// the utilities get to be lazy and just use large static arrays + +extern int nummodels; +extern dmodel_t dmodels[MAX_MAP_MODELS]; + +extern int visdatasize; +extern byte dvisdata[MAX_MAP_VISIBILITY]; + +extern int lightdatasize; +extern byte dlightdata[MAX_MAP_LIGHTING]; + +extern int texdatasize; +extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) + +extern int entdatasize; +extern char dentdata[MAX_MAP_ENTSTRING]; + +extern int numleafs; +extern dleaf_t dleafs[MAX_MAP_LEAFS]; + +extern int numplanes; +extern dplane_t dplanes[MAX_MAP_PLANES]; + +extern int numvertexes; +extern dvertex_t dvertexes[MAX_MAP_VERTS]; + +extern int numnodes; +extern dnode_t dnodes[MAX_MAP_NODES]; + +extern int numtexinfo; +extern texinfo_t texinfo[MAX_MAP_TEXINFO]; + +extern int numfaces; +extern dface_t dfaces[MAX_MAP_FACES]; + +extern int numclipnodes; +extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; + +extern int numedges; +extern dedge_t dedges[MAX_MAP_EDGES]; + +extern int nummarksurfaces; +extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; + +extern int numsurfedges; +extern int dsurfedges[MAX_MAP_SURFEDGES]; + + +void DecompressVis (byte *in, byte *decompressed); +int CompressVis (byte *vis, byte *dest); + +void LoadBSPFile (char *filename); +void WriteBSPFile (char *filename); +void PrintBSPFileSizes (void); + +//=============== + + +typedef struct epair_s +{ + struct epair_s *next; + char *key; + char *value; +} epair_t; + +typedef struct +{ + vec3_t origin; + int firstbrush; + int numbrushes; + epair_t *epairs; +} entity_t; + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities (void); +void UnparseEntities (void); + +void SetKeyValue (entity_t *ent, char *key, char *value); +char *ValueForKey (entity_t *ent, char *key); +// will return "" if not present + +vec_t FloatForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); + +epair_t *ParseEpair (void); + +#endif diff --git a/WinQuake/cd_audio.c b/WinQuake/cd_audio.c index 0393422..8b15de7 100644 --- a/WinQuake/cd_audio.c +++ b/WinQuake/cd_audio.c @@ -1,886 +1,886 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All -// rights reserved. - -#include -#include "quakedef.h" -#include "dosisms.h" - -extern cvar_t bgmvolume; - -#define ADDRESS_MODE_HSG 0 -#define ADDRESS_MODE_RED_BOOK 1 - -#define STATUS_ERROR_BIT 0x8000 -#define STATUS_BUSY_BIT 0x0200 -#define STATUS_DONE_BIT 0x0100 -#define STATUS_ERROR_MASK 0x00ff - -#define ERROR_WRITE_PROTECT 0 -#define ERROR_UNKNOWN_UNIT 1 -#define ERROR_DRIVE_NOT_READY 2 -#define ERROR_UNKNOWN_COMMAND 3 -#define ERROR_CRC_ERROR 4 -#define ERROR_BAD_REQUEST_LEN 5 -#define ERROR_SEEK_ERROR 6 -#define ERROR_UNKNOWN_MEDIA 7 -#define ERROR_SECTOR_NOT_FOUND 8 -#define ERROR_OUT_OF_PAPER 9 -#define ERROR_WRITE_FAULT 10 -#define ERROR_READ_FAULT 11 -#define ERROR_GENERAL_FAILURE 12 -#define ERROR_RESERVED_13 13 -#define ERROR_RESERVED_14 14 -#define ERROR_BAD_DISK_CHANGE 15 - -#define COMMAND_READ 3 -#define COMMAND_WRITE 12 -#define COMMAND_PLAY_AUDIO 132 -#define COMMAND_STOP_AUDIO 133 -#define COMMAND_RESUME_AUDIO 136 - -#define READ_REQUEST_AUDIO_CHANNEL_INFO 4 -#define READ_REQUEST_DEVICE_STATUS 6 -#define READ_REQUEST_MEDIA_CHANGE 9 -#define READ_REQUEST_AUDIO_DISK_INFO 10 -#define READ_REQUEST_AUDIO_TRACK_INFO 11 -#define READ_REQUEST_AUDIO_STATUS 15 - -#define WRITE_REQUEST_EJECT 0 -#define WRITE_REQUEST_RESET 2 -#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3 - -#define STATUS_DOOR_OPEN 0x00000001 -#define STATUS_DOOR_UNLOCKED 0x00000002 -#define STATUS_RAW_SUPPORT 0x00000004 -#define STATUS_READ_WRITE 0x00000008 -#define STATUS_AUDIO_SUPPORT 0x00000010 -#define STATUS_INTERLEAVE_SUPPORT 0x00000020 -#define STATUS_BIT_6_RESERVED 0x00000040 -#define STATUS_PREFETCH_SUPPORT 0x00000080 -#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100 -#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200 - -#define MEDIA_NOT_CHANGED 1 -#define MEDIA_STATUS_UNKNOWN 0 -#define MEDIA_CHANGED -1 - -#define AUDIO_CONTROL_MASK 0xd0 -#define AUDIO_CONTROL_DATA_TRACK 0x40 -#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00 -#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10 -#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80 -#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90 - -#define AUDIO_STATUS_PAUSED 0x0001 - -#pragma pack(1) - -struct playAudioRequest -{ - char addressingMode; - int startLocation; - int sectors; -}; - -struct readRequest -{ - char mediaDescriptor; - short bufferOffset; - short bufferSegment; - short length; - short startSector; - int volumeID; -}; - -struct writeRequest -{ - char mediaDescriptor; - short bufferOffset; - short bufferSegment; - short length; - short startSector; - int volumeID; -}; - -struct cd_request -{ - char headerLength; - char unit; - char command; - short status; - char reserved[8]; - union - { - struct playAudioRequest playAudio; - struct readRequest read; - struct writeRequest write; - } x; -}; - - -struct audioChannelInfo_s -{ - char code; - char channel0input; - char channel0volume; - char channel1input; - char channel1volume; - char channel2input; - char channel2volume; - char channel3input; - char channel3volume; -}; - -struct deviceStatus_s -{ - char code; - int status; -}; - -struct mediaChange_s -{ - char code; - char status; -}; - -struct audioDiskInfo_s -{ - char code; - char lowTrack; - char highTrack; - int leadOutStart; -}; - -struct audioTrackInfo_s -{ - char code; - char track; - int start; - char control; -}; - -struct audioStatus_s -{ - char code; - short status; - int PRstartLocation; - int PRendLocation; -}; - -struct reset_s -{ - char code; -}; - -union readInfo_u -{ - struct audioChannelInfo_s audioChannelInfo; - struct deviceStatus_s deviceStatus; - struct mediaChange_s mediaChange; - struct audioDiskInfo_s audioDiskInfo; - struct audioTrackInfo_s audioTrackInfo; - struct audioStatus_s audioStatus; - struct reset_s reset; -}; - -#pragma pack() - -#define MAXIMUM_TRACKS 100 - -typedef struct -{ - int start; - int length; - qboolean isData; -} track_info; - -typedef struct -{ - qboolean valid; - int leadOutAddress; - track_info track[MAXIMUM_TRACKS]; - byte lowTrack; - byte highTrack; -} cd_info; - -static struct cd_request *cdRequest; -static union readInfo_u *readInfo; -static cd_info cd; - -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean mediaCheck = false; -static qboolean initialized = false; -static qboolean enabled = true; -static qboolean playLooping = false; -static short cdRequestSegment; -static short cdRequestOffset; -static short readInfoSegment; -static short readInfoOffset; -static byte remap[256]; -static byte cdrom; -static byte playTrack; -static byte cdvolume; - - -static int RedBookToSector(int rb) -{ - byte minute; - byte second; - byte frame; - - minute = (rb >> 16) & 0xff; - second = (rb >> 8) & 0xff; - frame = rb & 0xff; - return minute * 60 * 75 + second * 75 + frame; -} - - -static void CDAudio_Reset(void) -{ - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_WRITE; - cdRequest->status = 0; - - cdRequest->x.write.mediaDescriptor = 0; - cdRequest->x.write.bufferOffset = readInfoOffset; - cdRequest->x.write.bufferSegment = readInfoSegment; - cdRequest->x.write.length = sizeof(struct reset_s); - cdRequest->x.write.startSector = 0; - cdRequest->x.write.volumeID = 0; - - readInfo->reset.code = WRITE_REQUEST_RESET; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); -} - - -static void CDAudio_Eject(void) -{ - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_WRITE; - cdRequest->status = 0; - - cdRequest->x.write.mediaDescriptor = 0; - cdRequest->x.write.bufferOffset = readInfoOffset; - cdRequest->x.write.bufferSegment = readInfoSegment; - cdRequest->x.write.length = sizeof(struct reset_s); - cdRequest->x.write.startSector = 0; - cdRequest->x.write.volumeID = 0; - - readInfo->reset.code = WRITE_REQUEST_EJECT; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); -} - - -static int CDAudio_GetAudioTrackInfo(byte track, int *start) -{ - byte control; - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_READ; - cdRequest->status = 0; - - cdRequest->x.read.mediaDescriptor = 0; - cdRequest->x.read.bufferOffset = readInfoOffset; - cdRequest->x.read.bufferSegment = readInfoSegment; - cdRequest->x.read.length = sizeof(struct audioTrackInfo_s); - cdRequest->x.read.startSector = 0; - cdRequest->x.read.volumeID = 0; - - readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO; - readInfo->audioTrackInfo.track = track; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - if (cdRequest->status & STATUS_ERROR_BIT) - { - Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff); - return -1; - } - - *start = readInfo->audioTrackInfo.start; - control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK; - return (control & AUDIO_CONTROL_DATA_TRACK); -} - - -static int CDAudio_GetAudioDiskInfo(void) -{ - int n; - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_READ; - cdRequest->status = 0; - - cdRequest->x.read.mediaDescriptor = 0; - cdRequest->x.read.bufferOffset = readInfoOffset; - cdRequest->x.read.bufferSegment = readInfoSegment; - cdRequest->x.read.length = sizeof(struct audioDiskInfo_s); - cdRequest->x.read.startSector = 0; - cdRequest->x.read.volumeID = 0; - - readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - if (cdRequest->status & STATUS_ERROR_BIT) - { - Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff); - return -1; - } - - cd.valid = true; - cd.lowTrack = readInfo->audioDiskInfo.lowTrack; - cd.highTrack = readInfo->audioDiskInfo.highTrack; - cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart; - - for (n = cd.lowTrack; n <= cd.highTrack; n++) - { - cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start); - if (n > cd.lowTrack) - { - cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start); - if (n == cd.highTrack) - cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start); - } - } - - return 0; -} - - -static int CDAudio_GetAudioStatus(void) -{ - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_READ; - cdRequest->status = 0; - - cdRequest->x.read.mediaDescriptor = 0; - cdRequest->x.read.bufferOffset = readInfoOffset; - cdRequest->x.read.bufferSegment = readInfoSegment; - cdRequest->x.read.length = sizeof(struct audioStatus_s); - cdRequest->x.read.startSector = 0; - cdRequest->x.read.volumeID = 0; - - readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - if (cdRequest->status & STATUS_ERROR_BIT) - return -1; - return 0; -} - - -static int CDAudio_MediaChange(void) -{ - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_READ; - cdRequest->status = 0; - - cdRequest->x.read.mediaDescriptor = 0; - cdRequest->x.read.bufferOffset = readInfoOffset; - cdRequest->x.read.bufferSegment = readInfoSegment; - cdRequest->x.read.length = sizeof(struct mediaChange_s); - cdRequest->x.read.startSector = 0; - cdRequest->x.read.volumeID = 0; - - readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - return readInfo->mediaChange.status; -} - - -// we set the volume to 0 first and then to the desired volume -// some cd-rom drivers seem to need it done this way -void CDAudio_SetVolume (byte volume) -{ - if (!initialized || !enabled) - return; - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_WRITE; - cdRequest->status = 0; - - cdRequest->x.read.mediaDescriptor = 0; - cdRequest->x.read.bufferOffset = readInfoOffset; - cdRequest->x.read.bufferSegment = readInfoSegment; - cdRequest->x.read.length = sizeof(struct audioChannelInfo_s); - cdRequest->x.read.startSector = 0; - cdRequest->x.read.volumeID = 0; - - readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO; - readInfo->audioChannelInfo.channel0input = 0; - readInfo->audioChannelInfo.channel0volume = 0; - readInfo->audioChannelInfo.channel1input = 1; - readInfo->audioChannelInfo.channel1volume = 0; - readInfo->audioChannelInfo.channel2input = 2; - readInfo->audioChannelInfo.channel2volume = 0; - readInfo->audioChannelInfo.channel3input = 3; - readInfo->audioChannelInfo.channel3volume = 0; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - readInfo->audioChannelInfo.channel0volume = volume; - readInfo->audioChannelInfo.channel1volume = volume; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - cdvolume = volume; -} - - -void CDAudio_Play(byte track, qboolean looping) -{ - int volume; - - if (!initialized || !enabled) - return; - - if (!cd.valid) - return; - - track = remap[track]; - - if (playing) - { - if (playTrack == track) - return; - CDAudio_Stop(); - } - - playLooping = looping; - - if (track < cd.lowTrack || track > cd.highTrack) - { - Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track); - return; - } - - playTrack = track; - - if (cd.track[track].isData) - { - Con_DPrintf("CDAudio_Play: Can not play data.\n"); - return; - } - - volume = (int)(bgmvolume.value * 255.0); - if (volume < 0) - { - Cvar_SetValue ("bgmvolume", 0.0); - volume = 0; - } - else if (volume > 255) - { - Cvar_SetValue ("bgmvolume", 1.0); - volume = 255; - } - CDAudio_SetVolume (volume); - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_PLAY_AUDIO; - cdRequest->status = 0; - - cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK; - cdRequest->x.playAudio.startLocation = cd.track[track].start; - cdRequest->x.playAudio.sectors = cd.track[track].length; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - if (cdRequest->status & STATUS_ERROR_BIT) - { - Con_DPrintf("CDAudio_Play: track %u failed\n", track); - cd.valid = false; - playing = false; - return; - } - - playing = true; -} - - -void CDAudio_Stop(void) -{ - if (!initialized || !enabled) - return; - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_STOP_AUDIO; - cdRequest->status = 0; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - wasPlaying = playing; - playing = false; -} - - -void CDAudio_Pause(void) -{ - CDAudio_Stop(); -} - - -void CDAudio_Resume(void) -{ - if (!initialized || !enabled) - return; - - if (!cd.valid) - return; - - if (!wasPlaying) - return; - - cdRequest->headerLength = 13; - cdRequest->unit = 0; - cdRequest->command = COMMAND_RESUME_AUDIO; - cdRequest->status = 0; - - regs.x.ax = 0x1510; - regs.x.cx = cdrom; - regs.x.es = cdRequestSegment; - regs.x.bx = cdRequestOffset; - dos_int86 (0x2f); - - playing = true; -} - - -static void CD_f (void) -{ - char *command; - int ret; - int n; - int startAddress; - - if (Cmd_Argc() < 2) - return; - - command = Cmd_Argv (1); - - if (Q_strcasecmp(command, "on") == 0) - { - enabled = true; - return; - } - - if (Q_strcasecmp(command, "off") == 0) - { - if (playing) - CDAudio_Stop(); - enabled = false; - return; - } - - if (Q_strcasecmp(command, "reset") == 0) - { - enabled = true; - if (playing) - CDAudio_Stop(); - for (n = 0; n < 256; n++) - remap[n] = n; - CDAudio_Reset(); - CDAudio_GetAudioDiskInfo(); - return; - } - - if (Q_strcasecmp(command, "remap") == 0) - { - ret = Cmd_Argc() - 2; - if (ret <= 0) - { - for (n = 1; n < 256; n++) - if (remap[n] != n) - Con_Printf(" %u -> %u\n", n, remap[n]); - return; - } - for (n = 1; n <= ret; n++) - remap[n] = Q_atoi(Cmd_Argv (n+1)); - return; - } - - if (!cd.valid) - { - Con_Printf("No CD in player.\n"); - return; - } - - if (Q_strcasecmp(command, "play") == 0) - { - CDAudio_Play(Q_atoi(Cmd_Argv (2)), false); - return; - } - - if (Q_strcasecmp(command, "loop") == 0) - { - CDAudio_Play(Q_atoi(Cmd_Argv (2)), true); - return; - } - - if (Q_strcasecmp(command, "stop") == 0) - { - CDAudio_Stop(); - return; - } - - if (Q_strcasecmp(command, "pause") == 0) - { - CDAudio_Pause(); - return; - } - - if (Q_strcasecmp(command, "resume") == 0) - { - CDAudio_Resume(); - return; - } - - if (Q_strcasecmp(command, "eject") == 0) - { - if (playing) - CDAudio_Stop(); - CDAudio_Eject(); - cd.valid = false; - return; - } - - if (Q_strcasecmp(command, "info") == 0) - { - Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1); - for (n = cd.lowTrack; n <= cd.highTrack; n++) - { - ret = CDAudio_GetAudioTrackInfo (n, &startAddress); - Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff); - } - if (playing) - Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); - Con_Printf("Volume is %u\n", cdvolume); - CDAudio_MediaChange(); - Con_Printf("Status %04x\n", cdRequest->status & 0xffff); - return; - } -} - - -void CDAudio_Update(void) -{ - int ret; - int newVolume; - static double lastUpdate; - - if (!initialized || !enabled) - return; - - if ((realtime - lastUpdate) < 0.25) - return; - lastUpdate = realtime; - - if (mediaCheck) - { - static double lastCheck; - - if ((realtime - lastCheck) < 5.0) - return; - lastCheck = realtime; - - ret = CDAudio_MediaChange(); - if (ret == MEDIA_CHANGED) - { - Con_DPrintf("CDAudio: media changed\n"); - playing = false; - wasPlaying = false; - cd.valid = false; - CDAudio_GetAudioDiskInfo(); - return; - } - } - - newVolume = (int)(bgmvolume.value * 255.0); - if (newVolume != cdvolume) - { - if (newVolume < 0) - { - Cvar_SetValue ("bgmvolume", 0.0); - newVolume = 0; - } - else if (newVolume > 255) - { - Cvar_SetValue ("bgmvolume", 1.0); - newVolume = 255; - } - CDAudio_SetVolume (newVolume); - } - - if (playing) - { - CDAudio_GetAudioStatus(); - if ((cdRequest->status & STATUS_BUSY_BIT) == 0) - { - playing = false; - if (playLooping) - CDAudio_Play(playTrack, true); - } - } -} - - -int CDAudio_Init(void) -{ - char *memory; - int n; - - if (cls.state == ca_dedicated) - return -1; - - if (COM_CheckParm("-nocdaudio")) - return -1; - - if (COM_CheckParm("-cdmediacheck")) - mediaCheck = true; - - regs.x.ax = 0x1500; - regs.x.bx = 0; - dos_int86 (0x2f); - if (regs.x.bx == 0) - { - Con_NotifyBox ( - "MSCDEX not loaded, music is\n" - "disabled. Use \"-nocdaudio\" if you\n" - "wish to avoid this message in the\n" - "future. See README.TXT for help.\n" - ); - return -1; - } - if (regs.x.bx > 1) - Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n"); - cdrom = regs.x.cx; - - regs.x.ax = 0x150c; - regs.x.bx = 0; - dos_int86 (0x2f); - if (regs.x.bx == 0) - { - Con_NotifyBox ( - "MSCDEX version 2.00 or later\n" - "required for music. See README.TXT\n" - "for help.\n" - ); - Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n"); - return -1; - } - - memory = dos_getmemory(sizeof(struct cd_request -) + sizeof(union readInfo_u)); - if (memory == NULL) - { - Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n"); - return -1; - } - - cdRequest = (struct cd_request *)memory; - cdRequestSegment = ptr2real(cdRequest) >> 4; - cdRequestOffset = ptr2real(cdRequest) & 0xf; - - readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request)); - readInfoSegment = ptr2real(readInfo) >> 4; - readInfoOffset = ptr2real(readInfo) & 0xf; - - for (n = 0; n < 256; n++) - remap[n] = n; - initialized = true; - - CDAudio_SetVolume (255); - if (CDAudio_GetAudioDiskInfo()) - { - Con_Printf("CDAudio_Init: No CD in player.\n"); - enabled = false; - } - - Cmd_AddCommand ("cd", CD_f); - - Con_Printf("CD Audio Initialized\n"); - - return 0; -} - - -void CDAudio_Shutdown(void) -{ - if (!initialized) - return; - CDAudio_Stop(); -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All +// rights reserved. + +#include +#include "quakedef.h" +#include "dosisms.h" + +extern cvar_t bgmvolume; + +#define ADDRESS_MODE_HSG 0 +#define ADDRESS_MODE_RED_BOOK 1 + +#define STATUS_ERROR_BIT 0x8000 +#define STATUS_BUSY_BIT 0x0200 +#define STATUS_DONE_BIT 0x0100 +#define STATUS_ERROR_MASK 0x00ff + +#define ERROR_WRITE_PROTECT 0 +#define ERROR_UNKNOWN_UNIT 1 +#define ERROR_DRIVE_NOT_READY 2 +#define ERROR_UNKNOWN_COMMAND 3 +#define ERROR_CRC_ERROR 4 +#define ERROR_BAD_REQUEST_LEN 5 +#define ERROR_SEEK_ERROR 6 +#define ERROR_UNKNOWN_MEDIA 7 +#define ERROR_SECTOR_NOT_FOUND 8 +#define ERROR_OUT_OF_PAPER 9 +#define ERROR_WRITE_FAULT 10 +#define ERROR_READ_FAULT 11 +#define ERROR_GENERAL_FAILURE 12 +#define ERROR_RESERVED_13 13 +#define ERROR_RESERVED_14 14 +#define ERROR_BAD_DISK_CHANGE 15 + +#define COMMAND_READ 3 +#define COMMAND_WRITE 12 +#define COMMAND_PLAY_AUDIO 132 +#define COMMAND_STOP_AUDIO 133 +#define COMMAND_RESUME_AUDIO 136 + +#define READ_REQUEST_AUDIO_CHANNEL_INFO 4 +#define READ_REQUEST_DEVICE_STATUS 6 +#define READ_REQUEST_MEDIA_CHANGE 9 +#define READ_REQUEST_AUDIO_DISK_INFO 10 +#define READ_REQUEST_AUDIO_TRACK_INFO 11 +#define READ_REQUEST_AUDIO_STATUS 15 + +#define WRITE_REQUEST_EJECT 0 +#define WRITE_REQUEST_RESET 2 +#define WRITE_REQUEST_AUDIO_CHANNEL_INFO 3 + +#define STATUS_DOOR_OPEN 0x00000001 +#define STATUS_DOOR_UNLOCKED 0x00000002 +#define STATUS_RAW_SUPPORT 0x00000004 +#define STATUS_READ_WRITE 0x00000008 +#define STATUS_AUDIO_SUPPORT 0x00000010 +#define STATUS_INTERLEAVE_SUPPORT 0x00000020 +#define STATUS_BIT_6_RESERVED 0x00000040 +#define STATUS_PREFETCH_SUPPORT 0x00000080 +#define STATUS_AUDIO_MANIPLUATION_SUPPORT 0x00000100 +#define STATUS_RED_BOOK_ADDRESS_SUPPORT 0x00000200 + +#define MEDIA_NOT_CHANGED 1 +#define MEDIA_STATUS_UNKNOWN 0 +#define MEDIA_CHANGED -1 + +#define AUDIO_CONTROL_MASK 0xd0 +#define AUDIO_CONTROL_DATA_TRACK 0x40 +#define AUDIO_CONTROL_AUDIO_2_TRACK 0x00 +#define AUDIO_CONTROL_AUDIO_2P_TRACK 0x10 +#define AUDIO_CONTROL_AUDIO_4_TRACK 0x80 +#define AUDIO_CONTROL_AUDIO_4P_TRACK 0x90 + +#define AUDIO_STATUS_PAUSED 0x0001 + +#pragma pack(1) + +struct playAudioRequest +{ + char addressingMode; + int startLocation; + int sectors; +}; + +struct readRequest +{ + char mediaDescriptor; + short bufferOffset; + short bufferSegment; + short length; + short startSector; + int volumeID; +}; + +struct writeRequest +{ + char mediaDescriptor; + short bufferOffset; + short bufferSegment; + short length; + short startSector; + int volumeID; +}; + +struct cd_request +{ + char headerLength; + char unit; + char command; + short status; + char reserved[8]; + union + { + struct playAudioRequest playAudio; + struct readRequest read; + struct writeRequest write; + } x; +}; + + +struct audioChannelInfo_s +{ + char code; + char channel0input; + char channel0volume; + char channel1input; + char channel1volume; + char channel2input; + char channel2volume; + char channel3input; + char channel3volume; +}; + +struct deviceStatus_s +{ + char code; + int status; +}; + +struct mediaChange_s +{ + char code; + char status; +}; + +struct audioDiskInfo_s +{ + char code; + char lowTrack; + char highTrack; + int leadOutStart; +}; + +struct audioTrackInfo_s +{ + char code; + char track; + int start; + char control; +}; + +struct audioStatus_s +{ + char code; + short status; + int PRstartLocation; + int PRendLocation; +}; + +struct reset_s +{ + char code; +}; + +union readInfo_u +{ + struct audioChannelInfo_s audioChannelInfo; + struct deviceStatus_s deviceStatus; + struct mediaChange_s mediaChange; + struct audioDiskInfo_s audioDiskInfo; + struct audioTrackInfo_s audioTrackInfo; + struct audioStatus_s audioStatus; + struct reset_s reset; +}; + +#pragma pack() + +#define MAXIMUM_TRACKS 100 + +typedef struct +{ + int start; + int length; + qboolean isData; +} track_info; + +typedef struct +{ + qboolean valid; + int leadOutAddress; + track_info track[MAXIMUM_TRACKS]; + byte lowTrack; + byte highTrack; +} cd_info; + +static struct cd_request *cdRequest; +static union readInfo_u *readInfo; +static cd_info cd; + +static qboolean playing = false; +static qboolean wasPlaying = false; +static qboolean mediaCheck = false; +static qboolean initialized = false; +static qboolean enabled = true; +static qboolean playLooping = false; +static short cdRequestSegment; +static short cdRequestOffset; +static short readInfoSegment; +static short readInfoOffset; +static byte remap[256]; +static byte cdrom; +static byte playTrack; +static byte cdvolume; + + +static int RedBookToSector(int rb) +{ + byte minute; + byte second; + byte frame; + + minute = (rb >> 16) & 0xff; + second = (rb >> 8) & 0xff; + frame = rb & 0xff; + return minute * 60 * 75 + second * 75 + frame; +} + + +static void CDAudio_Reset(void) +{ + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_WRITE; + cdRequest->status = 0; + + cdRequest->x.write.mediaDescriptor = 0; + cdRequest->x.write.bufferOffset = readInfoOffset; + cdRequest->x.write.bufferSegment = readInfoSegment; + cdRequest->x.write.length = sizeof(struct reset_s); + cdRequest->x.write.startSector = 0; + cdRequest->x.write.volumeID = 0; + + readInfo->reset.code = WRITE_REQUEST_RESET; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); +} + + +static void CDAudio_Eject(void) +{ + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_WRITE; + cdRequest->status = 0; + + cdRequest->x.write.mediaDescriptor = 0; + cdRequest->x.write.bufferOffset = readInfoOffset; + cdRequest->x.write.bufferSegment = readInfoSegment; + cdRequest->x.write.length = sizeof(struct reset_s); + cdRequest->x.write.startSector = 0; + cdRequest->x.write.volumeID = 0; + + readInfo->reset.code = WRITE_REQUEST_EJECT; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); +} + + +static int CDAudio_GetAudioTrackInfo(byte track, int *start) +{ + byte control; + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_READ; + cdRequest->status = 0; + + cdRequest->x.read.mediaDescriptor = 0; + cdRequest->x.read.bufferOffset = readInfoOffset; + cdRequest->x.read.bufferSegment = readInfoSegment; + cdRequest->x.read.length = sizeof(struct audioTrackInfo_s); + cdRequest->x.read.startSector = 0; + cdRequest->x.read.volumeID = 0; + + readInfo->audioTrackInfo.code = READ_REQUEST_AUDIO_TRACK_INFO; + readInfo->audioTrackInfo.track = track; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + if (cdRequest->status & STATUS_ERROR_BIT) + { + Con_DPrintf("CDAudio_GetAudioTrackInfo %04x\n", cdRequest->status & 0xffff); + return -1; + } + + *start = readInfo->audioTrackInfo.start; + control = readInfo->audioTrackInfo.control & AUDIO_CONTROL_MASK; + return (control & AUDIO_CONTROL_DATA_TRACK); +} + + +static int CDAudio_GetAudioDiskInfo(void) +{ + int n; + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_READ; + cdRequest->status = 0; + + cdRequest->x.read.mediaDescriptor = 0; + cdRequest->x.read.bufferOffset = readInfoOffset; + cdRequest->x.read.bufferSegment = readInfoSegment; + cdRequest->x.read.length = sizeof(struct audioDiskInfo_s); + cdRequest->x.read.startSector = 0; + cdRequest->x.read.volumeID = 0; + + readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_DISK_INFO; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + if (cdRequest->status & STATUS_ERROR_BIT) + { + Con_DPrintf("CDAudio_GetAudioDiskInfo %04x\n", cdRequest->status & 0xffff); + return -1; + } + + cd.valid = true; + cd.lowTrack = readInfo->audioDiskInfo.lowTrack; + cd.highTrack = readInfo->audioDiskInfo.highTrack; + cd.leadOutAddress = readInfo->audioDiskInfo.leadOutStart; + + for (n = cd.lowTrack; n <= cd.highTrack; n++) + { + cd.track[n].isData = CDAudio_GetAudioTrackInfo (n, &cd.track[n].start); + if (n > cd.lowTrack) + { + cd.track[n-1].length = RedBookToSector(cd.track[n].start) - RedBookToSector(cd.track[n-1].start); + if (n == cd.highTrack) + cd.track[n].length = RedBookToSector(cd.leadOutAddress) - RedBookToSector(cd.track[n].start); + } + } + + return 0; +} + + +static int CDAudio_GetAudioStatus(void) +{ + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_READ; + cdRequest->status = 0; + + cdRequest->x.read.mediaDescriptor = 0; + cdRequest->x.read.bufferOffset = readInfoOffset; + cdRequest->x.read.bufferSegment = readInfoSegment; + cdRequest->x.read.length = sizeof(struct audioStatus_s); + cdRequest->x.read.startSector = 0; + cdRequest->x.read.volumeID = 0; + + readInfo->audioDiskInfo.code = READ_REQUEST_AUDIO_STATUS; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + if (cdRequest->status & STATUS_ERROR_BIT) + return -1; + return 0; +} + + +static int CDAudio_MediaChange(void) +{ + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_READ; + cdRequest->status = 0; + + cdRequest->x.read.mediaDescriptor = 0; + cdRequest->x.read.bufferOffset = readInfoOffset; + cdRequest->x.read.bufferSegment = readInfoSegment; + cdRequest->x.read.length = sizeof(struct mediaChange_s); + cdRequest->x.read.startSector = 0; + cdRequest->x.read.volumeID = 0; + + readInfo->mediaChange.code = READ_REQUEST_MEDIA_CHANGE; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + return readInfo->mediaChange.status; +} + + +// we set the volume to 0 first and then to the desired volume +// some cd-rom drivers seem to need it done this way +void CDAudio_SetVolume (byte volume) +{ + if (!initialized || !enabled) + return; + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_WRITE; + cdRequest->status = 0; + + cdRequest->x.read.mediaDescriptor = 0; + cdRequest->x.read.bufferOffset = readInfoOffset; + cdRequest->x.read.bufferSegment = readInfoSegment; + cdRequest->x.read.length = sizeof(struct audioChannelInfo_s); + cdRequest->x.read.startSector = 0; + cdRequest->x.read.volumeID = 0; + + readInfo->audioChannelInfo.code = WRITE_REQUEST_AUDIO_CHANNEL_INFO; + readInfo->audioChannelInfo.channel0input = 0; + readInfo->audioChannelInfo.channel0volume = 0; + readInfo->audioChannelInfo.channel1input = 1; + readInfo->audioChannelInfo.channel1volume = 0; + readInfo->audioChannelInfo.channel2input = 2; + readInfo->audioChannelInfo.channel2volume = 0; + readInfo->audioChannelInfo.channel3input = 3; + readInfo->audioChannelInfo.channel3volume = 0; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + readInfo->audioChannelInfo.channel0volume = volume; + readInfo->audioChannelInfo.channel1volume = volume; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + cdvolume = volume; +} + + +void CDAudio_Play(byte track, qboolean looping) +{ + int volume; + + if (!initialized || !enabled) + return; + + if (!cd.valid) + return; + + track = remap[track]; + + if (playing) + { + if (playTrack == track) + return; + CDAudio_Stop(); + } + + playLooping = looping; + + if (track < cd.lowTrack || track > cd.highTrack) + { + Con_DPrintf("CDAudio_Play: Bad track number %u.\n", track); + return; + } + + playTrack = track; + + if (cd.track[track].isData) + { + Con_DPrintf("CDAudio_Play: Can not play data.\n"); + return; + } + + volume = (int)(bgmvolume.value * 255.0); + if (volume < 0) + { + Cvar_SetValue ("bgmvolume", 0.0); + volume = 0; + } + else if (volume > 255) + { + Cvar_SetValue ("bgmvolume", 1.0); + volume = 255; + } + CDAudio_SetVolume (volume); + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_PLAY_AUDIO; + cdRequest->status = 0; + + cdRequest->x.playAudio.addressingMode = ADDRESS_MODE_RED_BOOK; + cdRequest->x.playAudio.startLocation = cd.track[track].start; + cdRequest->x.playAudio.sectors = cd.track[track].length; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + if (cdRequest->status & STATUS_ERROR_BIT) + { + Con_DPrintf("CDAudio_Play: track %u failed\n", track); + cd.valid = false; + playing = false; + return; + } + + playing = true; +} + + +void CDAudio_Stop(void) +{ + if (!initialized || !enabled) + return; + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_STOP_AUDIO; + cdRequest->status = 0; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + wasPlaying = playing; + playing = false; +} + + +void CDAudio_Pause(void) +{ + CDAudio_Stop(); +} + + +void CDAudio_Resume(void) +{ + if (!initialized || !enabled) + return; + + if (!cd.valid) + return; + + if (!wasPlaying) + return; + + cdRequest->headerLength = 13; + cdRequest->unit = 0; + cdRequest->command = COMMAND_RESUME_AUDIO; + cdRequest->status = 0; + + regs.x.ax = 0x1510; + regs.x.cx = cdrom; + regs.x.es = cdRequestSegment; + regs.x.bx = cdRequestOffset; + dos_int86 (0x2f); + + playing = true; +} + + +static void CD_f (void) +{ + char *command; + int ret; + int n; + int startAddress; + + if (Cmd_Argc() < 2) + return; + + command = Cmd_Argv (1); + + if (Q_strcasecmp(command, "on") == 0) + { + enabled = true; + return; + } + + if (Q_strcasecmp(command, "off") == 0) + { + if (playing) + CDAudio_Stop(); + enabled = false; + return; + } + + if (Q_strcasecmp(command, "reset") == 0) + { + enabled = true; + if (playing) + CDAudio_Stop(); + for (n = 0; n < 256; n++) + remap[n] = n; + CDAudio_Reset(); + CDAudio_GetAudioDiskInfo(); + return; + } + + if (Q_strcasecmp(command, "remap") == 0) + { + ret = Cmd_Argc() - 2; + if (ret <= 0) + { + for (n = 1; n < 256; n++) + if (remap[n] != n) + Con_Printf(" %u -> %u\n", n, remap[n]); + return; + } + for (n = 1; n <= ret; n++) + remap[n] = Q_atoi(Cmd_Argv (n+1)); + return; + } + + if (!cd.valid) + { + Con_Printf("No CD in player.\n"); + return; + } + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play(Q_atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play(Q_atoi(Cmd_Argv (2)), true); + return; + } + + if (Q_strcasecmp(command, "stop") == 0) + { + CDAudio_Stop(); + return; + } + + if (Q_strcasecmp(command, "pause") == 0) + { + CDAudio_Pause(); + return; + } + + if (Q_strcasecmp(command, "resume") == 0) + { + CDAudio_Resume(); + return; + } + + if (Q_strcasecmp(command, "eject") == 0) + { + if (playing) + CDAudio_Stop(); + CDAudio_Eject(); + cd.valid = false; + return; + } + + if (Q_strcasecmp(command, "info") == 0) + { + Con_Printf("%u tracks\n", cd.highTrack - cd.lowTrack + 1); + for (n = cd.lowTrack; n <= cd.highTrack; n++) + { + ret = CDAudio_GetAudioTrackInfo (n, &startAddress); + Con_Printf("Track %2u: %s at %2u:%02u\n", n, ret ? "data " : "music", (startAddress >> 16) & 0xff, (startAddress >> 8) & 0xff); + } + if (playing) + Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); + Con_Printf("Volume is %u\n", cdvolume); + CDAudio_MediaChange(); + Con_Printf("Status %04x\n", cdRequest->status & 0xffff); + return; + } +} + + +void CDAudio_Update(void) +{ + int ret; + int newVolume; + static double lastUpdate; + + if (!initialized || !enabled) + return; + + if ((realtime - lastUpdate) < 0.25) + return; + lastUpdate = realtime; + + if (mediaCheck) + { + static double lastCheck; + + if ((realtime - lastCheck) < 5.0) + return; + lastCheck = realtime; + + ret = CDAudio_MediaChange(); + if (ret == MEDIA_CHANGED) + { + Con_DPrintf("CDAudio: media changed\n"); + playing = false; + wasPlaying = false; + cd.valid = false; + CDAudio_GetAudioDiskInfo(); + return; + } + } + + newVolume = (int)(bgmvolume.value * 255.0); + if (newVolume != cdvolume) + { + if (newVolume < 0) + { + Cvar_SetValue ("bgmvolume", 0.0); + newVolume = 0; + } + else if (newVolume > 255) + { + Cvar_SetValue ("bgmvolume", 1.0); + newVolume = 255; + } + CDAudio_SetVolume (newVolume); + } + + if (playing) + { + CDAudio_GetAudioStatus(); + if ((cdRequest->status & STATUS_BUSY_BIT) == 0) + { + playing = false; + if (playLooping) + CDAudio_Play(playTrack, true); + } + } +} + + +int CDAudio_Init(void) +{ + char *memory; + int n; + + if (cls.state == ca_dedicated) + return -1; + + if (COM_CheckParm("-nocdaudio")) + return -1; + + if (COM_CheckParm("-cdmediacheck")) + mediaCheck = true; + + regs.x.ax = 0x1500; + regs.x.bx = 0; + dos_int86 (0x2f); + if (regs.x.bx == 0) + { + Con_NotifyBox ( + "MSCDEX not loaded, music is\n" + "disabled. Use \"-nocdaudio\" if you\n" + "wish to avoid this message in the\n" + "future. See README.TXT for help.\n" + ); + return -1; + } + if (regs.x.bx > 1) + Con_DPrintf("CDAudio_Init: First CD-ROM drive will be used\n"); + cdrom = regs.x.cx; + + regs.x.ax = 0x150c; + regs.x.bx = 0; + dos_int86 (0x2f); + if (regs.x.bx == 0) + { + Con_NotifyBox ( + "MSCDEX version 2.00 or later\n" + "required for music. See README.TXT\n" + "for help.\n" + ); + Con_DPrintf("CDAudio_Init: MSCDEX version 2.00 or later required.\n"); + return -1; + } + + memory = dos_getmemory(sizeof(struct cd_request +) + sizeof(union readInfo_u)); + if (memory == NULL) + { + Con_DPrintf("CDAudio_Init: Unable to allocate low memory.\n"); + return -1; + } + + cdRequest = (struct cd_request *)memory; + cdRequestSegment = ptr2real(cdRequest) >> 4; + cdRequestOffset = ptr2real(cdRequest) & 0xf; + + readInfo = (union readInfo_u *)(memory + sizeof(struct cd_request)); + readInfoSegment = ptr2real(readInfo) >> 4; + readInfoOffset = ptr2real(readInfo) & 0xf; + + for (n = 0; n < 256; n++) + remap[n] = n; + initialized = true; + + CDAudio_SetVolume (255); + if (CDAudio_GetAudioDiskInfo()) + { + Con_Printf("CDAudio_Init: No CD in player.\n"); + enabled = false; + } + + Cmd_AddCommand ("cd", CD_f); + + Con_Printf("CD Audio Initialized\n"); + + return 0; +} + + +void CDAudio_Shutdown(void) +{ + if (!initialized) + return; + CDAudio_Stop(); +} diff --git a/WinQuake/cd_linux.c b/WinQuake/cd_linux.c index 0e23d96..68f90e7 100644 --- a/WinQuake/cd_linux.c +++ b/WinQuake/cd_linux.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All // rights reserved. diff --git a/WinQuake/cd_null.c b/WinQuake/cd_null.c index d5eeec8..98f2e2e 100644 --- a/WinQuake/cd_null.c +++ b/WinQuake/cd_null.c @@ -1,55 +1,55 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -void CDAudio_Play(byte track, qboolean looping) -{ -} - - -void CDAudio_Stop(void) -{ -} - - -void CDAudio_Pause(void) -{ -} - - -void CDAudio_Resume(void) -{ -} - - -void CDAudio_Update(void) -{ -} - - -int CDAudio_Init(void) -{ - return 0; -} - - -void CDAudio_Shutdown(void) -{ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +void CDAudio_Play(byte track, qboolean looping) +{ +} + + +void CDAudio_Stop(void) +{ +} + + +void CDAudio_Pause(void) +{ +} + + +void CDAudio_Resume(void) +{ +} + + +void CDAudio_Update(void) +{ +} + + +int CDAudio_Init(void) +{ + return 0; +} + + +void CDAudio_Shutdown(void) +{ } \ No newline at end of file diff --git a/WinQuake/cd_win.c b/WinQuake/cd_win.c index 8672556..8143308 100644 --- a/WinQuake/cd_win.c +++ b/WinQuake/cd_win.c @@ -1,477 +1,477 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All -// rights reserved. - -#include -#include "quakedef.h" - -extern HWND mainwindow; -extern cvar_t bgmvolume; - -static qboolean cdValid = false; -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean initialized = false; -static qboolean enabled = false; -static qboolean playLooping = false; -static float cdvolume; -static byte remap[100]; -static byte cdrom; -static byte playTrack; -static byte maxTrack; - -UINT wDeviceID; - - -static void CDAudio_Eject(void) -{ - DWORD dwReturn; - - if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) - Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn); -} - - -static void CDAudio_CloseDoor(void) -{ - DWORD dwReturn; - - if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL)) - Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn); -} - - -static int CDAudio_GetAudioDiskInfo(void) -{ - DWORD dwReturn; - MCI_STATUS_PARMS mciStatusParms; - - - cdValid = false; - - mciStatusParms.dwItem = MCI_STATUS_READY; - dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: drive ready test - get status failed\n"); - return -1; - } - if (!mciStatusParms.dwReturn) - { - Con_DPrintf("CDAudio: drive not ready\n"); - return -1; - } - - mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; - dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: get tracks - status failed\n"); - return -1; - } - if (mciStatusParms.dwReturn < 1) - { - Con_DPrintf("CDAudio: no music tracks\n"); - return -1; - } - - cdValid = true; - maxTrack = mciStatusParms.dwReturn; - - return 0; -} - - -void CDAudio_Play(byte track, qboolean looping) -{ - DWORD dwReturn; - MCI_PLAY_PARMS mciPlayParms; - MCI_STATUS_PARMS mciStatusParms; - - if (!enabled) - return; - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - return; - } - - track = remap[track]; - - if (track < 1 || track > maxTrack) - { - Con_DPrintf("CDAudio: Bad track number %u.\n", track); - return; - } - - // don't try to play a non-audio track - mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK; - mciStatusParms.dwTrack = track; - dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); - if (dwReturn) - { - Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); - return; - } - if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) - { - Con_Printf("CDAudio: track %i is not audio\n", track); - return; - } - - // get the length of the track to be played - mciStatusParms.dwItem = MCI_STATUS_LENGTH; - mciStatusParms.dwTrack = track; - dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); - if (dwReturn) - { - Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); - return; - } - - if (playing) - { - if (playTrack == track) - return; - CDAudio_Stop(); - } - - mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0); - mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track; - mciPlayParms.dwCallback = (DWORD)mainwindow; - dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); - return; - } - - playLooping = looping; - playTrack = track; - playing = true; - - if (cdvolume == 0.0) - CDAudio_Pause (); -} - - -void CDAudio_Stop(void) -{ - DWORD dwReturn; - - if (!enabled) - return; - - if (!playing) - return; - - if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) - Con_DPrintf("MCI_STOP failed (%i)", dwReturn); - - wasPlaying = false; - playing = false; -} - - -void CDAudio_Pause(void) -{ - DWORD dwReturn; - MCI_GENERIC_PARMS mciGenericParms; - - if (!enabled) - return; - - if (!playing) - return; - - mciGenericParms.dwCallback = (DWORD)mainwindow; - if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) - Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn); - - wasPlaying = playing; - playing = false; -} - - -void CDAudio_Resume(void) -{ - DWORD dwReturn; - MCI_PLAY_PARMS mciPlayParms; - - if (!enabled) - return; - - if (!cdValid) - return; - - if (!wasPlaying) - return; - - mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0); - mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0); - mciPlayParms.dwCallback = (DWORD)mainwindow; - dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); - if (dwReturn) - { - Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); - return; - } - playing = true; -} - - -static void CD_f (void) -{ - char *command; - int ret; - int n; - int startAddress; - - if (Cmd_Argc() < 2) - return; - - command = Cmd_Argv (1); - - if (Q_strcasecmp(command, "on") == 0) - { - enabled = true; - return; - } - - if (Q_strcasecmp(command, "off") == 0) - { - if (playing) - CDAudio_Stop(); - enabled = false; - return; - } - - if (Q_strcasecmp(command, "reset") == 0) - { - enabled = true; - if (playing) - CDAudio_Stop(); - for (n = 0; n < 100; n++) - remap[n] = n; - CDAudio_GetAudioDiskInfo(); - return; - } - - if (Q_strcasecmp(command, "remap") == 0) - { - ret = Cmd_Argc() - 2; - if (ret <= 0) - { - for (n = 1; n < 100; n++) - if (remap[n] != n) - Con_Printf(" %u -> %u\n", n, remap[n]); - return; - } - for (n = 1; n <= ret; n++) - remap[n] = Q_atoi(Cmd_Argv (n+1)); - return; - } - - if (Q_strcasecmp(command, "close") == 0) - { - CDAudio_CloseDoor(); - return; - } - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - { - Con_Printf("No CD in player.\n"); - return; - } - } - - if (Q_strcasecmp(command, "play") == 0) - { - CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); - return; - } - - if (Q_strcasecmp(command, "loop") == 0) - { - CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); - return; - } - - if (Q_strcasecmp(command, "stop") == 0) - { - CDAudio_Stop(); - return; - } - - if (Q_strcasecmp(command, "pause") == 0) - { - CDAudio_Pause(); - return; - } - - if (Q_strcasecmp(command, "resume") == 0) - { - CDAudio_Resume(); - return; - } - - if (Q_strcasecmp(command, "eject") == 0) - { - if (playing) - CDAudio_Stop(); - CDAudio_Eject(); - cdValid = false; - return; - } - - if (Q_strcasecmp(command, "info") == 0) - { - Con_Printf("%u tracks\n", maxTrack); - if (playing) - Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); - else if (wasPlaying) - Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); - Con_Printf("Volume is %f\n", cdvolume); - return; - } -} - - -LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (lParam != wDeviceID) - return 1; - - switch (wParam) - { - case MCI_NOTIFY_SUCCESSFUL: - if (playing) - { - playing = false; - if (playLooping) - CDAudio_Play(playTrack, true); - } - break; - - case MCI_NOTIFY_ABORTED: - case MCI_NOTIFY_SUPERSEDED: - break; - - case MCI_NOTIFY_FAILURE: - Con_DPrintf("MCI_NOTIFY_FAILURE\n"); - CDAudio_Stop (); - cdValid = false; - break; - - default: - Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); - return 1; - } - - return 0; -} - - -void CDAudio_Update(void) -{ - if (!enabled) - return; - - if (bgmvolume.value != cdvolume) - { - if (cdvolume) - { - Cvar_SetValue ("bgmvolume", 0.0); - cdvolume = bgmvolume.value; - CDAudio_Pause (); - } - else - { - Cvar_SetValue ("bgmvolume", 1.0); - cdvolume = bgmvolume.value; - CDAudio_Resume (); - } - } -} - - -int CDAudio_Init(void) -{ - DWORD dwReturn; - MCI_OPEN_PARMS mciOpenParms; - MCI_SET_PARMS mciSetParms; - int n; - - if (cls.state == ca_dedicated) - return -1; - - if (COM_CheckParm("-nocdaudio")) - return -1; - - mciOpenParms.lpstrDeviceType = "cdaudio"; - if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) - { - Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn); - return -1; - } - wDeviceID = mciOpenParms.wDeviceID; - - // Set the time format to track/minute/second/frame (TMSF). - mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; - if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms)) - { - Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn); - mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); - return -1; - } - - for (n = 0; n < 100; n++) - remap[n] = n; - initialized = true; - enabled = true; - - if (CDAudio_GetAudioDiskInfo()) - { - Con_Printf("CDAudio_Init: No CD in player.\n"); - cdValid = false; - } - - Cmd_AddCommand ("cd", CD_f); - - Con_Printf("CD Audio Initialized\n"); - - return 0; -} - - -void CDAudio_Shutdown(void) -{ - if (!initialized) - return; - CDAudio_Stop(); - if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL)) - Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All +// rights reserved. + +#include +#include "quakedef.h" + +extern HWND mainwindow; +extern cvar_t bgmvolume; + +static qboolean cdValid = false; +static qboolean playing = false; +static qboolean wasPlaying = false; +static qboolean initialized = false; +static qboolean enabled = false; +static qboolean playLooping = false; +static float cdvolume; +static byte remap[100]; +static byte cdrom; +static byte playTrack; +static byte maxTrack; + +UINT wDeviceID; + + +static void CDAudio_Eject(void) +{ + DWORD dwReturn; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD)NULL)) + Con_DPrintf("MCI_SET_DOOR_OPEN failed (%i)\n", dwReturn); +} + + +static void CDAudio_CloseDoor(void) +{ + DWORD dwReturn; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD)NULL)) + Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%i)\n", dwReturn); +} + + +static int CDAudio_GetAudioDiskInfo(void) +{ + DWORD dwReturn; + MCI_STATUS_PARMS mciStatusParms; + + + cdValid = false; + + mciStatusParms.dwItem = MCI_STATUS_READY; + dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: drive ready test - get status failed\n"); + return -1; + } + if (!mciStatusParms.dwReturn) + { + Con_DPrintf("CDAudio: drive not ready\n"); + return -1; + } + + mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; + dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: get tracks - status failed\n"); + return -1; + } + if (mciStatusParms.dwReturn < 1) + { + Con_DPrintf("CDAudio: no music tracks\n"); + return -1; + } + + cdValid = true; + maxTrack = mciStatusParms.dwReturn; + + return 0; +} + + +void CDAudio_Play(byte track, qboolean looping) +{ + DWORD dwReturn; + MCI_PLAY_PARMS mciPlayParms; + MCI_STATUS_PARMS mciStatusParms; + + if (!enabled) + return; + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + return; + } + + track = remap[track]; + + if (track < 1 || track > maxTrack) + { + Con_DPrintf("CDAudio: Bad track number %u.\n", track); + return; + } + + // don't try to play a non-audio track + mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK; + mciStatusParms.dwTrack = track; + dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); + if (dwReturn) + { + Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); + return; + } + if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) + { + Con_Printf("CDAudio: track %i is not audio\n", track); + return; + } + + // get the length of the track to be played + mciStatusParms.dwItem = MCI_STATUS_LENGTH; + mciStatusParms.dwTrack = track; + dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD) (LPVOID) &mciStatusParms); + if (dwReturn) + { + Con_DPrintf("MCI_STATUS failed (%i)\n", dwReturn); + return; + } + + if (playing) + { + if (playTrack == track) + return; + CDAudio_Stop(); + } + + mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0); + mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track; + mciPlayParms.dwCallback = (DWORD)mainwindow; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + + playLooping = looping; + playTrack = track; + playing = true; + + if (cdvolume == 0.0) + CDAudio_Pause (); +} + + +void CDAudio_Stop(void) +{ + DWORD dwReturn; + + if (!enabled) + return; + + if (!playing) + return; + + if (dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD)NULL)) + Con_DPrintf("MCI_STOP failed (%i)", dwReturn); + + wasPlaying = false; + playing = false; +} + + +void CDAudio_Pause(void) +{ + DWORD dwReturn; + MCI_GENERIC_PARMS mciGenericParms; + + if (!enabled) + return; + + if (!playing) + return; + + mciGenericParms.dwCallback = (DWORD)mainwindow; + if (dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD)(LPVOID) &mciGenericParms)) + Con_DPrintf("MCI_PAUSE failed (%i)", dwReturn); + + wasPlaying = playing; + playing = false; +} + + +void CDAudio_Resume(void) +{ + DWORD dwReturn; + MCI_PLAY_PARMS mciPlayParms; + + if (!enabled) + return; + + if (!cdValid) + return; + + if (!wasPlaying) + return; + + mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0); + mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0); + mciPlayParms.dwCallback = (DWORD)mainwindow; + dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms); + if (dwReturn) + { + Con_DPrintf("CDAudio: MCI_PLAY failed (%i)\n", dwReturn); + return; + } + playing = true; +} + + +static void CD_f (void) +{ + char *command; + int ret; + int n; + int startAddress; + + if (Cmd_Argc() < 2) + return; + + command = Cmd_Argv (1); + + if (Q_strcasecmp(command, "on") == 0) + { + enabled = true; + return; + } + + if (Q_strcasecmp(command, "off") == 0) + { + if (playing) + CDAudio_Stop(); + enabled = false; + return; + } + + if (Q_strcasecmp(command, "reset") == 0) + { + enabled = true; + if (playing) + CDAudio_Stop(); + for (n = 0; n < 100; n++) + remap[n] = n; + CDAudio_GetAudioDiskInfo(); + return; + } + + if (Q_strcasecmp(command, "remap") == 0) + { + ret = Cmd_Argc() - 2; + if (ret <= 0) + { + for (n = 1; n < 100; n++) + if (remap[n] != n) + Con_Printf(" %u -> %u\n", n, remap[n]); + return; + } + for (n = 1; n <= ret; n++) + remap[n] = Q_atoi(Cmd_Argv (n+1)); + return; + } + + if (Q_strcasecmp(command, "close") == 0) + { + CDAudio_CloseDoor(); + return; + } + + if (!cdValid) + { + CDAudio_GetAudioDiskInfo(); + if (!cdValid) + { + Con_Printf("No CD in player.\n"); + return; + } + } + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true); + return; + } + + if (Q_strcasecmp(command, "stop") == 0) + { + CDAudio_Stop(); + return; + } + + if (Q_strcasecmp(command, "pause") == 0) + { + CDAudio_Pause(); + return; + } + + if (Q_strcasecmp(command, "resume") == 0) + { + CDAudio_Resume(); + return; + } + + if (Q_strcasecmp(command, "eject") == 0) + { + if (playing) + CDAudio_Stop(); + CDAudio_Eject(); + cdValid = false; + return; + } + + if (Q_strcasecmp(command, "info") == 0) + { + Con_Printf("%u tracks\n", maxTrack); + if (playing) + Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack); + else if (wasPlaying) + Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack); + Con_Printf("Volume is %f\n", cdvolume); + return; + } +} + + +LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (lParam != wDeviceID) + return 1; + + switch (wParam) + { + case MCI_NOTIFY_SUCCESSFUL: + if (playing) + { + playing = false; + if (playLooping) + CDAudio_Play(playTrack, true); + } + break; + + case MCI_NOTIFY_ABORTED: + case MCI_NOTIFY_SUPERSEDED: + break; + + case MCI_NOTIFY_FAILURE: + Con_DPrintf("MCI_NOTIFY_FAILURE\n"); + CDAudio_Stop (); + cdValid = false; + break; + + default: + Con_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); + return 1; + } + + return 0; +} + + +void CDAudio_Update(void) +{ + if (!enabled) + return; + + if (bgmvolume.value != cdvolume) + { + if (cdvolume) + { + Cvar_SetValue ("bgmvolume", 0.0); + cdvolume = bgmvolume.value; + CDAudio_Pause (); + } + else + { + Cvar_SetValue ("bgmvolume", 1.0); + cdvolume = bgmvolume.value; + CDAudio_Resume (); + } + } +} + + +int CDAudio_Init(void) +{ + DWORD dwReturn; + MCI_OPEN_PARMS mciOpenParms; + MCI_SET_PARMS mciSetParms; + int n; + + if (cls.state == ca_dedicated) + return -1; + + if (COM_CheckParm("-nocdaudio")) + return -1; + + mciOpenParms.lpstrDeviceType = "cdaudio"; + if (dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD) (LPVOID) &mciOpenParms)) + { + Con_Printf("CDAudio_Init: MCI_OPEN failed (%i)\n", dwReturn); + return -1; + } + wDeviceID = mciOpenParms.wDeviceID; + + // Set the time format to track/minute/second/frame (TMSF). + mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID) &mciSetParms)) + { + Con_Printf("MCI_SET_TIME_FORMAT failed (%i)\n", dwReturn); + mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); + return -1; + } + + for (n = 0; n < 100; n++) + remap[n] = n; + initialized = true; + enabled = true; + + if (CDAudio_GetAudioDiskInfo()) + { + Con_Printf("CDAudio_Init: No CD in player.\n"); + cdValid = false; + } + + Cmd_AddCommand ("cd", CD_f); + + Con_Printf("CD Audio Initialized\n"); + + return 0; +} + + +void CDAudio_Shutdown(void) +{ + if (!initialized) + return; + CDAudio_Stop(); + if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL)) + Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n"); +} diff --git a/WinQuake/cdaudio.h b/WinQuake/cdaudio.h index 80e975b..30dfd30 100644 --- a/WinQuake/cdaudio.h +++ b/WinQuake/cdaudio.h @@ -1,27 +1,27 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -int CDAudio_Init(void); -void CDAudio_Play(byte track, qboolean looping); -void CDAudio_Stop(void); -void CDAudio_Pause(void); -void CDAudio_Resume(void); -void CDAudio_Shutdown(void); -void CDAudio_Update(void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +int CDAudio_Init(void); +void CDAudio_Play(byte track, qboolean looping); +void CDAudio_Stop(void); +void CDAudio_Pause(void); +void CDAudio_Resume(void); +void CDAudio_Shutdown(void); +void CDAudio_Update(void); diff --git a/WinQuake/chase.c b/WinQuake/chase.c index 23061e3..d986ad0 100644 --- a/WinQuake/chase.c +++ b/WinQuake/chase.c @@ -1,92 +1,92 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// chase.c -- chase camera code - -#include "quakedef.h" - -cvar_t chase_back = {"chase_back", "100"}; -cvar_t chase_up = {"chase_up", "16"}; -cvar_t chase_right = {"chase_right", "0"}; -cvar_t chase_active = {"chase_active", "0"}; - -vec3_t chase_pos; -vec3_t chase_angles; - -vec3_t chase_dest; -vec3_t chase_dest_angles; - - -void Chase_Init (void) -{ - Cvar_RegisterVariable (&chase_back); - Cvar_RegisterVariable (&chase_up); - Cvar_RegisterVariable (&chase_right); - Cvar_RegisterVariable (&chase_active); -} - -void Chase_Reset (void) -{ - // for respawning and teleporting -// start position 12 units behind head -} - -void TraceLine (vec3_t start, vec3_t end, vec3_t impact) -{ - trace_t trace; - - memset (&trace, 0, sizeof(trace)); - SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); - - VectorCopy (trace.endpos, impact); -} - -void Chase_Update (void) -{ - int i; - float dist; - vec3_t forward, up, right; - vec3_t dest, stop; - - - // if can't see player, reset - AngleVectors (cl.viewangles, forward, right, up); - - // calc exact destination - for (i=0 ; i<3 ; i++) - chase_dest[i] = r_refdef.vieworg[i] - - forward[i]*chase_back.value - - right[i]*chase_right.value; - chase_dest[2] = r_refdef.vieworg[2] + chase_up.value; - - // find the spot the player is looking at - VectorMA (r_refdef.vieworg, 4096, forward, dest); - TraceLine (r_refdef.vieworg, dest, stop); - - // calculate pitch to look at the same spot from camera - VectorSubtract (stop, r_refdef.vieworg, stop); - dist = DotProduct (stop, forward); - if (dist < 1) - dist = 1; - r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180; - - // move towards destination - VectorCopy (chase_dest, r_refdef.vieworg); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// chase.c -- chase camera code + +#include "quakedef.h" + +cvar_t chase_back = {"chase_back", "100"}; +cvar_t chase_up = {"chase_up", "16"}; +cvar_t chase_right = {"chase_right", "0"}; +cvar_t chase_active = {"chase_active", "0"}; + +vec3_t chase_pos; +vec3_t chase_angles; + +vec3_t chase_dest; +vec3_t chase_dest_angles; + + +void Chase_Init (void) +{ + Cvar_RegisterVariable (&chase_back); + Cvar_RegisterVariable (&chase_up); + Cvar_RegisterVariable (&chase_right); + Cvar_RegisterVariable (&chase_active); +} + +void Chase_Reset (void) +{ + // for respawning and teleporting +// start position 12 units behind head +} + +void TraceLine (vec3_t start, vec3_t end, vec3_t impact) +{ + trace_t trace; + + memset (&trace, 0, sizeof(trace)); + SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); + + VectorCopy (trace.endpos, impact); +} + +void Chase_Update (void) +{ + int i; + float dist; + vec3_t forward, up, right; + vec3_t dest, stop; + + + // if can't see player, reset + AngleVectors (cl.viewangles, forward, right, up); + + // calc exact destination + for (i=0 ; i<3 ; i++) + chase_dest[i] = r_refdef.vieworg[i] + - forward[i]*chase_back.value + - right[i]*chase_right.value; + chase_dest[2] = r_refdef.vieworg[2] + chase_up.value; + + // find the spot the player is looking at + VectorMA (r_refdef.vieworg, 4096, forward, dest); + TraceLine (r_refdef.vieworg, dest, stop); + + // calculate pitch to look at the same spot from camera + VectorSubtract (stop, r_refdef.vieworg, stop); + dist = DotProduct (stop, forward); + if (dist < 1) + dist = 1; + r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180; + + // move towards destination + VectorCopy (chase_dest, r_refdef.vieworg); +} + diff --git a/WinQuake/cl_demo.c b/WinQuake/cl_demo.c index 550368e..c025264 100644 --- a/WinQuake/cl_demo.c +++ b/WinQuake/cl_demo.c @@ -1,367 +1,367 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - -void CL_FinishTimeDemo (void); - -/* -============================================================================== - -DEMO CODE - -When a demo is playing back, all NET_SendMessages are skipped, and -NET_GetMessages are read from the demo file. - -Whenever cl.time gets past the last received message, another message is -read from the demo file. -============================================================================== -*/ - -/* -============== -CL_StopPlayback - -Called when a demo file runs out, or the user starts a game -============== -*/ -void CL_StopPlayback (void) -{ - if (!cls.demoplayback) - return; - - fclose (cls.demofile); - cls.demoplayback = false; - cls.demofile = NULL; - cls.state = ca_disconnected; - - if (cls.timedemo) - CL_FinishTimeDemo (); -} - -/* -==================== -CL_WriteDemoMessage - -Dumps the current net message, prefixed by the length and view angles -==================== -*/ -void CL_WriteDemoMessage (void) -{ - int len; - int i; - float f; - - len = LittleLong (net_message.cursize); - fwrite (&len, 4, 1, cls.demofile); - for (i=0 ; i<3 ; i++) - { - f = LittleFloat (cl.viewangles[i]); - fwrite (&f, 4, 1, cls.demofile); - } - fwrite (net_message.data, net_message.cursize, 1, cls.demofile); - fflush (cls.demofile); -} - -/* -==================== -CL_GetMessage - -Handles recording and playback of demos, on top of NET_ code -==================== -*/ -int CL_GetMessage (void) -{ - int r, i; - float f; - - if (cls.demoplayback) - { - // decide if it is time to grab the next message - if (cls.signon == SIGNONS) // allways grab until fully connected - { - if (cls.timedemo) - { - if (host_framecount == cls.td_lastframe) - return 0; // allready read this frame's message - cls.td_lastframe = host_framecount; - // if this is the second frame, grab the real td_starttime - // so the bogus time on the first frame doesn't count - if (host_framecount == cls.td_startframe + 1) - cls.td_starttime = realtime; - } - else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0]) - { - return 0; // don't need another message yet - } - } - - // get the next message - fread (&net_message.cursize, 4, 1, cls.demofile); - VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); - for (i=0 ; i<3 ; i++) - { - r = fread (&f, 4, 1, cls.demofile); - cl.mviewangles[0][i] = LittleFloat (f); - } - - net_message.cursize = LittleLong (net_message.cursize); - if (net_message.cursize > MAX_MSGLEN) - Sys_Error ("Demo message > MAX_MSGLEN"); - r = fread (net_message.data, net_message.cursize, 1, cls.demofile); - if (r != 1) - { - CL_StopPlayback (); - return 0; - } - - return 1; - } - - while (1) - { - r = NET_GetMessage (cls.netcon); - - if (r != 1 && r != 2) - return r; - - // discard nop keepalive message - if (net_message.cursize == 1 && net_message.data[0] == svc_nop) - Con_Printf ("<-- server to client keepalive\n"); - else - break; - } - - if (cls.demorecording) - CL_WriteDemoMessage (); - - return r; -} - - -/* -==================== -CL_Stop_f - -stop recording a demo -==================== -*/ -void CL_Stop_f (void) -{ - if (cmd_source != src_command) - return; - - if (!cls.demorecording) - { - Con_Printf ("Not recording a demo.\n"); - return; - } - -// write a disconnect message to the demo file - SZ_Clear (&net_message); - MSG_WriteByte (&net_message, svc_disconnect); - CL_WriteDemoMessage (); - -// finish up - fclose (cls.demofile); - cls.demofile = NULL; - cls.demorecording = false; - Con_Printf ("Completed demo\n"); -} - -/* -==================== -CL_Record_f - -record [cd track] -==================== -*/ -void CL_Record_f (void) -{ - int c; - char name[MAX_OSPATH]; - int track; - - if (cmd_source != src_command) - return; - - c = Cmd_Argc(); - if (c != 2 && c != 3 && c != 4) - { - Con_Printf ("record [ [cd track]]\n"); - return; - } - - if (strstr(Cmd_Argv(1), "..")) - { - Con_Printf ("Relative pathnames are not allowed.\n"); - return; - } - - if (c == 2 && cls.state == ca_connected) - { - Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n"); - return; - } - -// write the forced cd track number, or -1 - if (c == 4) - { - track = atoi(Cmd_Argv(3)); - Con_Printf ("Forcing CD track to %i\n", cls.forcetrack); - } - else - track = -1; - - sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); - -// -// start the map up -// - if (c > 2) - Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command); - -// -// open the demo file -// - COM_DefaultExtension (name, ".dem"); - - Con_Printf ("recording to %s.\n", name); - cls.demofile = fopen (name, "wb"); - if (!cls.demofile) - { - Con_Printf ("ERROR: couldn't open.\n"); - return; - } - - cls.forcetrack = track; - fprintf (cls.demofile, "%i\n", cls.forcetrack); - - cls.demorecording = true; -} - - -/* -==================== -CL_PlayDemo_f - -play [demoname] -==================== -*/ -void CL_PlayDemo_f (void) -{ - char name[256]; - int c; - qboolean neg = false; - - if (cmd_source != src_command) - return; - - if (Cmd_Argc() != 2) - { - Con_Printf ("play : plays a demo\n"); - return; - } - -// -// disconnect from server -// - CL_Disconnect (); - -// -// open the demo file -// - strcpy (name, Cmd_Argv(1)); - COM_DefaultExtension (name, ".dem"); - - Con_Printf ("Playing demo from %s.\n", name); - COM_FOpenFile (name, &cls.demofile); - if (!cls.demofile) - { - Con_Printf ("ERROR: couldn't open.\n"); - cls.demonum = -1; // stop demo loop - return; - } - - cls.demoplayback = true; - cls.state = ca_connected; - cls.forcetrack = 0; - - while ((c = getc(cls.demofile)) != '\n') - if (c == '-') - neg = true; - else - cls.forcetrack = cls.forcetrack * 10 + (c - '0'); - - if (neg) - cls.forcetrack = -cls.forcetrack; -// ZOID, fscanf is evil -// fscanf (cls.demofile, "%i\n", &cls.forcetrack); -} - -/* -==================== -CL_FinishTimeDemo - -==================== -*/ -void CL_FinishTimeDemo (void) -{ - int frames; - float time; - - cls.timedemo = false; - -// the first frame didn't count - frames = (host_framecount - cls.td_startframe) - 1; - time = realtime - cls.td_starttime; - if (!time) - time = 1; - Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time); -} - -/* -==================== -CL_TimeDemo_f - -timedemo [demoname] -==================== -*/ -void CL_TimeDemo_f (void) -{ - if (cmd_source != src_command) - return; - - if (Cmd_Argc() != 2) - { - Con_Printf ("timedemo : gets demo speeds\n"); - return; - } - - CL_PlayDemo_f (); - -// cls.td_starttime will be grabbed at the second frame of the demo, so -// all the loading time doesn't get counted - - cls.timedemo = true; - cls.td_startframe = host_framecount; - cls.td_lastframe = -1; // get a new message this frame -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +void CL_FinishTimeDemo (void); + +/* +============================================================================== + +DEMO CODE + +When a demo is playing back, all NET_SendMessages are skipped, and +NET_GetMessages are read from the demo file. + +Whenever cl.time gets past the last received message, another message is +read from the demo file. +============================================================================== +*/ + +/* +============== +CL_StopPlayback + +Called when a demo file runs out, or the user starts a game +============== +*/ +void CL_StopPlayback (void) +{ + if (!cls.demoplayback) + return; + + fclose (cls.demofile); + cls.demoplayback = false; + cls.demofile = NULL; + cls.state = ca_disconnected; + + if (cls.timedemo) + CL_FinishTimeDemo (); +} + +/* +==================== +CL_WriteDemoMessage + +Dumps the current net message, prefixed by the length and view angles +==================== +*/ +void CL_WriteDemoMessage (void) +{ + int len; + int i; + float f; + + len = LittleLong (net_message.cursize); + fwrite (&len, 4, 1, cls.demofile); + for (i=0 ; i<3 ; i++) + { + f = LittleFloat (cl.viewangles[i]); + fwrite (&f, 4, 1, cls.demofile); + } + fwrite (net_message.data, net_message.cursize, 1, cls.demofile); + fflush (cls.demofile); +} + +/* +==================== +CL_GetMessage + +Handles recording and playback of demos, on top of NET_ code +==================== +*/ +int CL_GetMessage (void) +{ + int r, i; + float f; + + if (cls.demoplayback) + { + // decide if it is time to grab the next message + if (cls.signon == SIGNONS) // allways grab until fully connected + { + if (cls.timedemo) + { + if (host_framecount == cls.td_lastframe) + return 0; // allready read this frame's message + cls.td_lastframe = host_framecount; + // if this is the second frame, grab the real td_starttime + // so the bogus time on the first frame doesn't count + if (host_framecount == cls.td_startframe + 1) + cls.td_starttime = realtime; + } + else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0]) + { + return 0; // don't need another message yet + } + } + + // get the next message + fread (&net_message.cursize, 4, 1, cls.demofile); + VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); + for (i=0 ; i<3 ; i++) + { + r = fread (&f, 4, 1, cls.demofile); + cl.mviewangles[0][i] = LittleFloat (f); + } + + net_message.cursize = LittleLong (net_message.cursize); + if (net_message.cursize > MAX_MSGLEN) + Sys_Error ("Demo message > MAX_MSGLEN"); + r = fread (net_message.data, net_message.cursize, 1, cls.demofile); + if (r != 1) + { + CL_StopPlayback (); + return 0; + } + + return 1; + } + + while (1) + { + r = NET_GetMessage (cls.netcon); + + if (r != 1 && r != 2) + return r; + + // discard nop keepalive message + if (net_message.cursize == 1 && net_message.data[0] == svc_nop) + Con_Printf ("<-- server to client keepalive\n"); + else + break; + } + + if (cls.demorecording) + CL_WriteDemoMessage (); + + return r; +} + + +/* +==================== +CL_Stop_f + +stop recording a demo +==================== +*/ +void CL_Stop_f (void) +{ + if (cmd_source != src_command) + return; + + if (!cls.demorecording) + { + Con_Printf ("Not recording a demo.\n"); + return; + } + +// write a disconnect message to the demo file + SZ_Clear (&net_message); + MSG_WriteByte (&net_message, svc_disconnect); + CL_WriteDemoMessage (); + +// finish up + fclose (cls.demofile); + cls.demofile = NULL; + cls.demorecording = false; + Con_Printf ("Completed demo\n"); +} + +/* +==================== +CL_Record_f + +record [cd track] +==================== +*/ +void CL_Record_f (void) +{ + int c; + char name[MAX_OSPATH]; + int track; + + if (cmd_source != src_command) + return; + + c = Cmd_Argc(); + if (c != 2 && c != 3 && c != 4) + { + Con_Printf ("record [ [cd track]]\n"); + return; + } + + if (strstr(Cmd_Argv(1), "..")) + { + Con_Printf ("Relative pathnames are not allowed.\n"); + return; + } + + if (c == 2 && cls.state == ca_connected) + { + Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n"); + return; + } + +// write the forced cd track number, or -1 + if (c == 4) + { + track = atoi(Cmd_Argv(3)); + Con_Printf ("Forcing CD track to %i\n", cls.forcetrack); + } + else + track = -1; + + sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); + +// +// start the map up +// + if (c > 2) + Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command); + +// +// open the demo file +// + COM_DefaultExtension (name, ".dem"); + + Con_Printf ("recording to %s.\n", name); + cls.demofile = fopen (name, "wb"); + if (!cls.demofile) + { + Con_Printf ("ERROR: couldn't open.\n"); + return; + } + + cls.forcetrack = track; + fprintf (cls.demofile, "%i\n", cls.forcetrack); + + cls.demorecording = true; +} + + +/* +==================== +CL_PlayDemo_f + +play [demoname] +==================== +*/ +void CL_PlayDemo_f (void) +{ + char name[256]; + int c; + qboolean neg = false; + + if (cmd_source != src_command) + return; + + if (Cmd_Argc() != 2) + { + Con_Printf ("play : plays a demo\n"); + return; + } + +// +// disconnect from server +// + CL_Disconnect (); + +// +// open the demo file +// + strcpy (name, Cmd_Argv(1)); + COM_DefaultExtension (name, ".dem"); + + Con_Printf ("Playing demo from %s.\n", name); + COM_FOpenFile (name, &cls.demofile); + if (!cls.demofile) + { + Con_Printf ("ERROR: couldn't open.\n"); + cls.demonum = -1; // stop demo loop + return; + } + + cls.demoplayback = true; + cls.state = ca_connected; + cls.forcetrack = 0; + + while ((c = getc(cls.demofile)) != '\n') + if (c == '-') + neg = true; + else + cls.forcetrack = cls.forcetrack * 10 + (c - '0'); + + if (neg) + cls.forcetrack = -cls.forcetrack; +// ZOID, fscanf is evil +// fscanf (cls.demofile, "%i\n", &cls.forcetrack); +} + +/* +==================== +CL_FinishTimeDemo + +==================== +*/ +void CL_FinishTimeDemo (void) +{ + int frames; + float time; + + cls.timedemo = false; + +// the first frame didn't count + frames = (host_framecount - cls.td_startframe) - 1; + time = realtime - cls.td_starttime; + if (!time) + time = 1; + Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time); +} + +/* +==================== +CL_TimeDemo_f + +timedemo [demoname] +==================== +*/ +void CL_TimeDemo_f (void) +{ + if (cmd_source != src_command) + return; + + if (Cmd_Argc() != 2) + { + Con_Printf ("timedemo : gets demo speeds\n"); + return; + } + + CL_PlayDemo_f (); + +// cls.td_starttime will be grabbed at the second frame of the demo, so +// all the loading time doesn't get counted + + cls.timedemo = true; + cls.td_startframe = host_framecount; + cls.td_lastframe = -1; // get a new message this frame +} + diff --git a/WinQuake/cl_input.c b/WinQuake/cl_input.c index 5327b73..41a7932 100644 --- a/WinQuake/cl_input.c +++ b/WinQuake/cl_input.c @@ -1,448 +1,448 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cl.input.c -- builds an intended movement command to send to the server - -// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All -// rights reserved. - -#include "quakedef.h" - -/* -=============================================================================== - -KEY BUTTONS - -Continuous button event tracking is complicated by the fact that two different -input sources (say, mouse button 1 and the control key) can both press the -same button, but the button should only be released when both of the -pressing key have been released. - -When a key event issues a button command (+forward, +attack, etc), it appends -its key number as a parameter to the command so it can be matched up with -the release. - -state bit 0 is the current state of the key -state bit 1 is edge triggered on the up to down transition -state bit 2 is edge triggered on the down to up transition - -=============================================================================== -*/ - - -kbutton_t in_mlook, in_klook; -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack; -kbutton_t in_up, in_down; - -int in_impulse; - - -void KeyDown (kbutton_t *b) -{ - int k; - char *c; - - c = Cmd_Argv(1); - if (c[0]) - k = atoi(c); - else - k = -1; // typed manually at the console for continuous down - - if (k == b->down[0] || k == b->down[1]) - return; // repeating key - - if (!b->down[0]) - b->down[0] = k; - else if (!b->down[1]) - b->down[1] = k; - else - { - Con_Printf ("Three keys down for a button!\n"); - return; - } - - if (b->state & 1) - return; // still down - b->state |= 1 + 2; // down + impulse down -} - -void KeyUp (kbutton_t *b) -{ - int k; - char *c; - - c = Cmd_Argv(1); - if (c[0]) - k = atoi(c); - else - { // typed manually at the console, assume for unsticking, so clear all - b->down[0] = b->down[1] = 0; - b->state = 4; // impulse up - return; - } - - if (b->down[0] == k) - b->down[0] = 0; - else if (b->down[1] == k) - b->down[1] = 0; - else - return; // key up without coresponding down (menu pass through) - if (b->down[0] || b->down[1]) - return; // some other key is still holding it down - - if (!(b->state & 1)) - return; // still up (this should not happen) - b->state &= ~1; // now up - b->state |= 4; // impulse up -} - -void IN_KLookDown (void) {KeyDown(&in_klook);} -void IN_KLookUp (void) {KeyUp(&in_klook);} -void IN_MLookDown (void) {KeyDown(&in_mlook);} -void IN_MLookUp (void) { -KeyUp(&in_mlook); -if ( !(in_mlook.state&1) && lookspring.value) - V_StartPitchDrift(); -} -void IN_UpDown(void) {KeyDown(&in_up);} -void IN_UpUp(void) {KeyUp(&in_up);} -void IN_DownDown(void) {KeyDown(&in_down);} -void IN_DownUp(void) {KeyUp(&in_down);} -void IN_LeftDown(void) {KeyDown(&in_left);} -void IN_LeftUp(void) {KeyUp(&in_left);} -void IN_RightDown(void) {KeyDown(&in_right);} -void IN_RightUp(void) {KeyUp(&in_right);} -void IN_ForwardDown(void) {KeyDown(&in_forward);} -void IN_ForwardUp(void) {KeyUp(&in_forward);} -void IN_BackDown(void) {KeyDown(&in_back);} -void IN_BackUp(void) {KeyUp(&in_back);} -void IN_LookupDown(void) {KeyDown(&in_lookup);} -void IN_LookupUp(void) {KeyUp(&in_lookup);} -void IN_LookdownDown(void) {KeyDown(&in_lookdown);} -void IN_LookdownUp(void) {KeyUp(&in_lookdown);} -void IN_MoveleftDown(void) {KeyDown(&in_moveleft);} -void IN_MoveleftUp(void) {KeyUp(&in_moveleft);} -void IN_MoverightDown(void) {KeyDown(&in_moveright);} -void IN_MoverightUp(void) {KeyUp(&in_moveright);} - -void IN_SpeedDown(void) {KeyDown(&in_speed);} -void IN_SpeedUp(void) {KeyUp(&in_speed);} -void IN_StrafeDown(void) {KeyDown(&in_strafe);} -void IN_StrafeUp(void) {KeyUp(&in_strafe);} - -void IN_AttackDown(void) {KeyDown(&in_attack);} -void IN_AttackUp(void) {KeyUp(&in_attack);} - -void IN_UseDown (void) {KeyDown(&in_use);} -void IN_UseUp (void) {KeyUp(&in_use);} -void IN_JumpDown (void) {KeyDown(&in_jump);} -void IN_JumpUp (void) {KeyUp(&in_jump);} - -void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));} - -/* -=============== -CL_KeyState - -Returns 0.25 if a key was pressed and released during the frame, -0.5 if it was pressed and held -0 if held then released, and -1.0 if held for the entire time -=============== -*/ -float CL_KeyState (kbutton_t *key) -{ - float val; - qboolean impulsedown, impulseup, down; - - impulsedown = key->state & 2; - impulseup = key->state & 4; - down = key->state & 1; - val = 0; - - if (impulsedown && !impulseup) - if (down) - val = 0.5; // pressed and held this frame - else - val = 0; // I_Error (); - if (impulseup && !impulsedown) - if (down) - val = 0; // I_Error (); - else - val = 0; // released this frame - if (!impulsedown && !impulseup) - if (down) - val = 1.0; // held the entire frame - else - val = 0; // up the entire frame - if (impulsedown && impulseup) - if (down) - val = 0.75; // released and re-pressed this frame - else - val = 0.25; // pressed and released this frame - - key->state &= 1; // clear impulses - - return val; -} - - - - -//========================================================================== - -cvar_t cl_upspeed = {"cl_upspeed","200"}; -cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true}; -cvar_t cl_backspeed = {"cl_backspeed","200", true}; -cvar_t cl_sidespeed = {"cl_sidespeed","350"}; - -cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"}; - -cvar_t cl_yawspeed = {"cl_yawspeed","140"}; -cvar_t cl_pitchspeed = {"cl_pitchspeed","150"}; - -cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"}; - - -/* -================ -CL_AdjustAngles - -Moves the local angle positions -================ -*/ -void CL_AdjustAngles (void) -{ - float speed; - float up, down; - - if (in_speed.state & 1) - speed = host_frametime * cl_anglespeedkey.value; - else - speed = host_frametime; - - if (!(in_strafe.state & 1)) - { - cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right); - cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left); - cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); - } - if (in_klook.state & 1) - { - V_StopPitchDrift (); - cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward); - cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back); - } - - up = CL_KeyState (&in_lookup); - down = CL_KeyState(&in_lookdown); - - cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; - cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down; - - if (up || down) - V_StopPitchDrift (); - - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - - if (cl.viewangles[ROLL] > 50) - cl.viewangles[ROLL] = 50; - if (cl.viewangles[ROLL] < -50) - cl.viewangles[ROLL] = -50; - -} - -/* -================ -CL_BaseMove - -Send the intended movement message to the server -================ -*/ -void CL_BaseMove (usercmd_t *cmd) -{ - if (cls.signon != SIGNONS) - return; - - CL_AdjustAngles (); - - Q_memset (cmd, 0, sizeof(*cmd)); - - if (in_strafe.state & 1) - { - cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right); - cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left); - } - - cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright); - cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft); - - cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up); - cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down); - - if (! (in_klook.state & 1) ) - { - cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward); - cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back); - } - -// -// adjust for speed key -// - if (in_speed.state & 1) - { - cmd->forwardmove *= cl_movespeedkey.value; - cmd->sidemove *= cl_movespeedkey.value; - cmd->upmove *= cl_movespeedkey.value; - } - -#ifdef QUAKE2 - cmd->lightlevel = cl.light_level; -#endif -} - - - -/* -============== -CL_SendMove -============== -*/ -void CL_SendMove (usercmd_t *cmd) -{ - int i; - int bits; - sizebuf_t buf; - byte data[128]; - - buf.maxsize = 128; - buf.cursize = 0; - buf.data = data; - - cl.cmd = *cmd; - -// -// send the movement message -// - MSG_WriteByte (&buf, clc_move); - - MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times - - for (i=0 ; i<3 ; i++) - MSG_WriteAngle (&buf, cl.viewangles[i]); - - MSG_WriteShort (&buf, cmd->forwardmove); - MSG_WriteShort (&buf, cmd->sidemove); - MSG_WriteShort (&buf, cmd->upmove); - -// -// send button bits -// - bits = 0; - - if ( in_attack.state & 3 ) - bits |= 1; - in_attack.state &= ~2; - - if (in_jump.state & 3) - bits |= 2; - in_jump.state &= ~2; - - MSG_WriteByte (&buf, bits); - - MSG_WriteByte (&buf, in_impulse); - in_impulse = 0; - -#ifdef QUAKE2 -// -// light level -// - MSG_WriteByte (&buf, cmd->lightlevel); -#endif - -// -// deliver the message -// - if (cls.demoplayback) - return; - -// -// allways dump the first two message, because it may contain leftover inputs -// from the last level -// - if (++cl.movemessages <= 2) - return; - - if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) - { - Con_Printf ("CL_SendMove: lost server connection\n"); - CL_Disconnect (); - } -} - -/* -============ -CL_InitInput -============ -*/ -void CL_InitInput (void) -{ - Cmd_AddCommand ("+moveup",IN_UpDown); - Cmd_AddCommand ("-moveup",IN_UpUp); - Cmd_AddCommand ("+movedown",IN_DownDown); - Cmd_AddCommand ("-movedown",IN_DownUp); - Cmd_AddCommand ("+left",IN_LeftDown); - Cmd_AddCommand ("-left",IN_LeftUp); - Cmd_AddCommand ("+right",IN_RightDown); - Cmd_AddCommand ("-right",IN_RightUp); - Cmd_AddCommand ("+forward",IN_ForwardDown); - Cmd_AddCommand ("-forward",IN_ForwardUp); - Cmd_AddCommand ("+back",IN_BackDown); - Cmd_AddCommand ("-back",IN_BackUp); - Cmd_AddCommand ("+lookup", IN_LookupDown); - Cmd_AddCommand ("-lookup", IN_LookupUp); - Cmd_AddCommand ("+lookdown", IN_LookdownDown); - Cmd_AddCommand ("-lookdown", IN_LookdownUp); - Cmd_AddCommand ("+strafe", IN_StrafeDown); - Cmd_AddCommand ("-strafe", IN_StrafeUp); - Cmd_AddCommand ("+moveleft", IN_MoveleftDown); - Cmd_AddCommand ("-moveleft", IN_MoveleftUp); - Cmd_AddCommand ("+moveright", IN_MoverightDown); - Cmd_AddCommand ("-moveright", IN_MoverightUp); - Cmd_AddCommand ("+speed", IN_SpeedDown); - Cmd_AddCommand ("-speed", IN_SpeedUp); - Cmd_AddCommand ("+attack", IN_AttackDown); - Cmd_AddCommand ("-attack", IN_AttackUp); - Cmd_AddCommand ("+use", IN_UseDown); - Cmd_AddCommand ("-use", IN_UseUp); - Cmd_AddCommand ("+jump", IN_JumpDown); - Cmd_AddCommand ("-jump", IN_JumpUp); - Cmd_AddCommand ("impulse", IN_Impulse); - Cmd_AddCommand ("+klook", IN_KLookDown); - Cmd_AddCommand ("-klook", IN_KLookUp); - Cmd_AddCommand ("+mlook", IN_MLookDown); - Cmd_AddCommand ("-mlook", IN_MLookUp); - -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cl.input.c -- builds an intended movement command to send to the server + +// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All +// rights reserved. + +#include "quakedef.h" + +/* +=============================================================================== + +KEY BUTTONS + +Continuous button event tracking is complicated by the fact that two different +input sources (say, mouse button 1 and the control key) can both press the +same button, but the button should only be released when both of the +pressing key have been released. + +When a key event issues a button command (+forward, +attack, etc), it appends +its key number as a parameter to the command so it can be matched up with +the release. + +state bit 0 is the current state of the key +state bit 1 is edge triggered on the up to down transition +state bit 2 is edge triggered on the down to up transition + +=============================================================================== +*/ + + +kbutton_t in_mlook, in_klook; +kbutton_t in_left, in_right, in_forward, in_back; +kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; +kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack; +kbutton_t in_up, in_down; + +int in_impulse; + + +void KeyDown (kbutton_t *b) +{ + int k; + char *c; + + c = Cmd_Argv(1); + if (c[0]) + k = atoi(c); + else + k = -1; // typed manually at the console for continuous down + + if (k == b->down[0] || k == b->down[1]) + return; // repeating key + + if (!b->down[0]) + b->down[0] = k; + else if (!b->down[1]) + b->down[1] = k; + else + { + Con_Printf ("Three keys down for a button!\n"); + return; + } + + if (b->state & 1) + return; // still down + b->state |= 1 + 2; // down + impulse down +} + +void KeyUp (kbutton_t *b) +{ + int k; + char *c; + + c = Cmd_Argv(1); + if (c[0]) + k = atoi(c); + else + { // typed manually at the console, assume for unsticking, so clear all + b->down[0] = b->down[1] = 0; + b->state = 4; // impulse up + return; + } + + if (b->down[0] == k) + b->down[0] = 0; + else if (b->down[1] == k) + b->down[1] = 0; + else + return; // key up without coresponding down (menu pass through) + if (b->down[0] || b->down[1]) + return; // some other key is still holding it down + + if (!(b->state & 1)) + return; // still up (this should not happen) + b->state &= ~1; // now up + b->state |= 4; // impulse up +} + +void IN_KLookDown (void) {KeyDown(&in_klook);} +void IN_KLookUp (void) {KeyUp(&in_klook);} +void IN_MLookDown (void) {KeyDown(&in_mlook);} +void IN_MLookUp (void) { +KeyUp(&in_mlook); +if ( !(in_mlook.state&1) && lookspring.value) + V_StartPitchDrift(); +} +void IN_UpDown(void) {KeyDown(&in_up);} +void IN_UpUp(void) {KeyUp(&in_up);} +void IN_DownDown(void) {KeyDown(&in_down);} +void IN_DownUp(void) {KeyUp(&in_down);} +void IN_LeftDown(void) {KeyDown(&in_left);} +void IN_LeftUp(void) {KeyUp(&in_left);} +void IN_RightDown(void) {KeyDown(&in_right);} +void IN_RightUp(void) {KeyUp(&in_right);} +void IN_ForwardDown(void) {KeyDown(&in_forward);} +void IN_ForwardUp(void) {KeyUp(&in_forward);} +void IN_BackDown(void) {KeyDown(&in_back);} +void IN_BackUp(void) {KeyUp(&in_back);} +void IN_LookupDown(void) {KeyDown(&in_lookup);} +void IN_LookupUp(void) {KeyUp(&in_lookup);} +void IN_LookdownDown(void) {KeyDown(&in_lookdown);} +void IN_LookdownUp(void) {KeyUp(&in_lookdown);} +void IN_MoveleftDown(void) {KeyDown(&in_moveleft);} +void IN_MoveleftUp(void) {KeyUp(&in_moveleft);} +void IN_MoverightDown(void) {KeyDown(&in_moveright);} +void IN_MoverightUp(void) {KeyUp(&in_moveright);} + +void IN_SpeedDown(void) {KeyDown(&in_speed);} +void IN_SpeedUp(void) {KeyUp(&in_speed);} +void IN_StrafeDown(void) {KeyDown(&in_strafe);} +void IN_StrafeUp(void) {KeyUp(&in_strafe);} + +void IN_AttackDown(void) {KeyDown(&in_attack);} +void IN_AttackUp(void) {KeyUp(&in_attack);} + +void IN_UseDown (void) {KeyDown(&in_use);} +void IN_UseUp (void) {KeyUp(&in_use);} +void IN_JumpDown (void) {KeyDown(&in_jump);} +void IN_JumpUp (void) {KeyUp(&in_jump);} + +void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));} + +/* +=============== +CL_KeyState + +Returns 0.25 if a key was pressed and released during the frame, +0.5 if it was pressed and held +0 if held then released, and +1.0 if held for the entire time +=============== +*/ +float CL_KeyState (kbutton_t *key) +{ + float val; + qboolean impulsedown, impulseup, down; + + impulsedown = key->state & 2; + impulseup = key->state & 4; + down = key->state & 1; + val = 0; + + if (impulsedown && !impulseup) + if (down) + val = 0.5; // pressed and held this frame + else + val = 0; // I_Error (); + if (impulseup && !impulsedown) + if (down) + val = 0; // I_Error (); + else + val = 0; // released this frame + if (!impulsedown && !impulseup) + if (down) + val = 1.0; // held the entire frame + else + val = 0; // up the entire frame + if (impulsedown && impulseup) + if (down) + val = 0.75; // released and re-pressed this frame + else + val = 0.25; // pressed and released this frame + + key->state &= 1; // clear impulses + + return val; +} + + + + +//========================================================================== + +cvar_t cl_upspeed = {"cl_upspeed","200"}; +cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true}; +cvar_t cl_backspeed = {"cl_backspeed","200", true}; +cvar_t cl_sidespeed = {"cl_sidespeed","350"}; + +cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"}; + +cvar_t cl_yawspeed = {"cl_yawspeed","140"}; +cvar_t cl_pitchspeed = {"cl_pitchspeed","150"}; + +cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"}; + + +/* +================ +CL_AdjustAngles + +Moves the local angle positions +================ +*/ +void CL_AdjustAngles (void) +{ + float speed; + float up, down; + + if (in_speed.state & 1) + speed = host_frametime * cl_anglespeedkey.value; + else + speed = host_frametime; + + if (!(in_strafe.state & 1)) + { + cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right); + cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left); + cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); + } + if (in_klook.state & 1) + { + V_StopPitchDrift (); + cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward); + cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back); + } + + up = CL_KeyState (&in_lookup); + down = CL_KeyState(&in_lookdown); + + cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; + cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down; + + if (up || down) + V_StopPitchDrift (); + + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + + if (cl.viewangles[ROLL] > 50) + cl.viewangles[ROLL] = 50; + if (cl.viewangles[ROLL] < -50) + cl.viewangles[ROLL] = -50; + +} + +/* +================ +CL_BaseMove + +Send the intended movement message to the server +================ +*/ +void CL_BaseMove (usercmd_t *cmd) +{ + if (cls.signon != SIGNONS) + return; + + CL_AdjustAngles (); + + Q_memset (cmd, 0, sizeof(*cmd)); + + if (in_strafe.state & 1) + { + cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right); + cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left); + } + + cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright); + cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft); + + cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up); + cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down); + + if (! (in_klook.state & 1) ) + { + cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward); + cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back); + } + +// +// adjust for speed key +// + if (in_speed.state & 1) + { + cmd->forwardmove *= cl_movespeedkey.value; + cmd->sidemove *= cl_movespeedkey.value; + cmd->upmove *= cl_movespeedkey.value; + } + +#ifdef QUAKE2 + cmd->lightlevel = cl.light_level; +#endif +} + + + +/* +============== +CL_SendMove +============== +*/ +void CL_SendMove (usercmd_t *cmd) +{ + int i; + int bits; + sizebuf_t buf; + byte data[128]; + + buf.maxsize = 128; + buf.cursize = 0; + buf.data = data; + + cl.cmd = *cmd; + +// +// send the movement message +// + MSG_WriteByte (&buf, clc_move); + + MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times + + for (i=0 ; i<3 ; i++) + MSG_WriteAngle (&buf, cl.viewangles[i]); + + MSG_WriteShort (&buf, cmd->forwardmove); + MSG_WriteShort (&buf, cmd->sidemove); + MSG_WriteShort (&buf, cmd->upmove); + +// +// send button bits +// + bits = 0; + + if ( in_attack.state & 3 ) + bits |= 1; + in_attack.state &= ~2; + + if (in_jump.state & 3) + bits |= 2; + in_jump.state &= ~2; + + MSG_WriteByte (&buf, bits); + + MSG_WriteByte (&buf, in_impulse); + in_impulse = 0; + +#ifdef QUAKE2 +// +// light level +// + MSG_WriteByte (&buf, cmd->lightlevel); +#endif + +// +// deliver the message +// + if (cls.demoplayback) + return; + +// +// allways dump the first two message, because it may contain leftover inputs +// from the last level +// + if (++cl.movemessages <= 2) + return; + + if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) + { + Con_Printf ("CL_SendMove: lost server connection\n"); + CL_Disconnect (); + } +} + +/* +============ +CL_InitInput +============ +*/ +void CL_InitInput (void) +{ + Cmd_AddCommand ("+moveup",IN_UpDown); + Cmd_AddCommand ("-moveup",IN_UpUp); + Cmd_AddCommand ("+movedown",IN_DownDown); + Cmd_AddCommand ("-movedown",IN_DownUp); + Cmd_AddCommand ("+left",IN_LeftDown); + Cmd_AddCommand ("-left",IN_LeftUp); + Cmd_AddCommand ("+right",IN_RightDown); + Cmd_AddCommand ("-right",IN_RightUp); + Cmd_AddCommand ("+forward",IN_ForwardDown); + Cmd_AddCommand ("-forward",IN_ForwardUp); + Cmd_AddCommand ("+back",IN_BackDown); + Cmd_AddCommand ("-back",IN_BackUp); + Cmd_AddCommand ("+lookup", IN_LookupDown); + Cmd_AddCommand ("-lookup", IN_LookupUp); + Cmd_AddCommand ("+lookdown", IN_LookdownDown); + Cmd_AddCommand ("-lookdown", IN_LookdownUp); + Cmd_AddCommand ("+strafe", IN_StrafeDown); + Cmd_AddCommand ("-strafe", IN_StrafeUp); + Cmd_AddCommand ("+moveleft", IN_MoveleftDown); + Cmd_AddCommand ("-moveleft", IN_MoveleftUp); + Cmd_AddCommand ("+moveright", IN_MoverightDown); + Cmd_AddCommand ("-moveright", IN_MoverightUp); + Cmd_AddCommand ("+speed", IN_SpeedDown); + Cmd_AddCommand ("-speed", IN_SpeedUp); + Cmd_AddCommand ("+attack", IN_AttackDown); + Cmd_AddCommand ("-attack", IN_AttackUp); + Cmd_AddCommand ("+use", IN_UseDown); + Cmd_AddCommand ("-use", IN_UseUp); + Cmd_AddCommand ("+jump", IN_JumpDown); + Cmd_AddCommand ("-jump", IN_JumpUp); + Cmd_AddCommand ("impulse", IN_Impulse); + Cmd_AddCommand ("+klook", IN_KLookDown); + Cmd_AddCommand ("-klook", IN_KLookUp); + Cmd_AddCommand ("+mlook", IN_MLookDown); + Cmd_AddCommand ("-mlook", IN_MLookUp); + +} + diff --git a/WinQuake/cl_main.c b/WinQuake/cl_main.c index 5812143..897b9a4 100644 --- a/WinQuake/cl_main.c +++ b/WinQuake/cl_main.c @@ -1,757 +1,757 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cl_main.c -- client main loop - -#include "quakedef.h" - -// we need to declare some mouse variables here, because the menu system -// references them even when on a unix system. - -// these two are not intended to be set directly -cvar_t cl_name = {"_cl_name", "player", true}; -cvar_t cl_color = {"_cl_color", "0", true}; - -cvar_t cl_shownet = {"cl_shownet","0"}; // can be 0, 1, or 2 -cvar_t cl_nolerp = {"cl_nolerp","0"}; - -cvar_t lookspring = {"lookspring","0", true}; -cvar_t lookstrafe = {"lookstrafe","0", true}; -cvar_t sensitivity = {"sensitivity","3", true}; - -cvar_t m_pitch = {"m_pitch","0.022", true}; -cvar_t m_yaw = {"m_yaw","0.022", true}; -cvar_t m_forward = {"m_forward","1", true}; -cvar_t m_side = {"m_side","0.8", true}; - - -client_static_t cls; -client_state_t cl; -// FIXME: put these on hunk? -efrag_t cl_efrags[MAX_EFRAGS]; -entity_t cl_entities[MAX_EDICTS]; -entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -dlight_t cl_dlights[MAX_DLIGHTS]; - -int cl_numvisedicts; -entity_t *cl_visedicts[MAX_VISEDICTS]; - -/* -===================== -CL_ClearState - -===================== -*/ -void CL_ClearState (void) -{ - int i; - - if (!sv.active) - Host_ClearMemory (); - -// wipe the entire cl structure - memset (&cl, 0, sizeof(cl)); - - SZ_Clear (&cls.message); - -// clear other arrays - memset (cl_efrags, 0, sizeof(cl_efrags)); - memset (cl_entities, 0, sizeof(cl_entities)); - memset (cl_dlights, 0, sizeof(cl_dlights)); - memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); - memset (cl_temp_entities, 0, sizeof(cl_temp_entities)); - memset (cl_beams, 0, sizeof(cl_beams)); - -// -// allocate the efrags and chain together into a free list -// - cl.free_efrags = cl_efrags; - for (i=0 ; i>4, ((int)cl_color.value)&15)); - - MSG_WriteByte (&cls.message, clc_stringcmd); - sprintf (str, "spawn %s", cls.spawnparms); - MSG_WriteString (&cls.message, str); - break; - - case 3: - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, "begin"); - Cache_Report (); // print remaining memory - break; - - case 4: - SCR_EndLoadingPlaque (); // allow normal screen updates - break; - } -} - -/* -===================== -CL_NextDemo - -Called to play the next demo in the demo loop -===================== -*/ -void CL_NextDemo (void) -{ - char str[1024]; - - if (cls.demonum == -1) - return; // don't play demos - - SCR_BeginLoadingPlaque (); - - if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) - { - cls.demonum = 0; - if (!cls.demos[cls.demonum][0]) - { - Con_Printf ("No demos listed with startdemos\n"); - cls.demonum = -1; - return; - } - } - - sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]); - Cbuf_InsertText (str); - cls.demonum++; -} - -/* -============== -CL_PrintEntities_f -============== -*/ -void CL_PrintEntities_f (void) -{ - entity_t *ent; - int i; - - for (i=0,ent=cl_entities ; imodel) - { - Con_Printf ("EMPTY\n"); - continue; - } - Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n" - ,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]); - } -} - - -/* -=============== -SetPal - -Debugging tool, just flashes the screen -=============== -*/ -void SetPal (int i) -{ -#if 0 - static int old; - byte pal[768]; - int c; - - if (i == old) - return; - old = i; - - if (i==0) - VID_SetPalette (host_basepal); - else if (i==1) - { - for (c=0 ; c<768 ; c+=3) - { - pal[c] = 0; - pal[c+1] = 255; - pal[c+2] = 0; - } - VID_SetPalette (pal); - } - else - { - for (c=0 ; c<768 ; c+=3) - { - pal[c] = 0; - pal[c+1] = 0; - pal[c+2] = 255; - } - VID_SetPalette (pal); - } -#endif -} - -/* -=============== -CL_AllocDlight - -=============== -*/ -dlight_t *CL_AllocDlight (int key) -{ - int i; - dlight_t *dl; - -// first look for an exact key match - if (key) - { - dl = cl_dlights; - for (i=0 ; ikey == key) - { - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; - } - } - } - -// then look for anything else - dl = cl_dlights; - for (i=0 ; idie < cl.time) - { - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; - } - } - - dl = &cl_dlights[0]; - memset (dl, 0, sizeof(*dl)); - dl->key = key; - return dl; -} - - -/* -=============== -CL_DecayLights - -=============== -*/ -void CL_DecayLights (void) -{ - int i; - dlight_t *dl; - float time; - - time = cl.time - cl.oldtime; - - dl = cl_dlights; - for (i=0 ; idie < cl.time || !dl->radius) - continue; - - dl->radius -= time*dl->decay; - if (dl->radius < 0) - dl->radius = 0; - } -} - - -/* -=============== -CL_LerpPoint - -Determines the fraction between the last two messages that the objects -should be put at. -=============== -*/ -float CL_LerpPoint (void) -{ - float f, frac; - - f = cl.mtime[0] - cl.mtime[1]; - - if (!f || cl_nolerp.value || cls.timedemo || sv.active) - { - cl.time = cl.mtime[0]; - return 1; - } - - if (f > 0.1) - { // dropped packet, or start of demo - cl.mtime[1] = cl.mtime[0] - 0.1; - f = 0.1; - } - frac = (cl.time - cl.mtime[1]) / f; -//Con_Printf ("frac: %f\n",frac); - if (frac < 0) - { - if (frac < -0.01) - { -SetPal(1); - cl.time = cl.mtime[1]; -// Con_Printf ("low frac\n"); - } - frac = 0; - } - else if (frac > 1) - { - if (frac > 1.01) - { -SetPal(2); - cl.time = cl.mtime[0]; -// Con_Printf ("high frac\n"); - } - frac = 1; - } - else - SetPal(0); - - return frac; -} - - -/* -=============== -CL_RelinkEntities -=============== -*/ -void CL_RelinkEntities (void) -{ - entity_t *ent; - int i, j; - float frac, f, d; - vec3_t delta; - float bobjrotate; - vec3_t oldorg; - dlight_t *dl; - -// determine partial update time - frac = CL_LerpPoint (); - - cl_numvisedicts = 0; - -// -// interpolate player info -// - for (i=0 ; i<3 ; i++) - cl.velocity[i] = cl.mvelocity[1][i] + - frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); - - if (cls.demoplayback) - { - // interpolate the angles - for (j=0 ; j<3 ; j++) - { - d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; - if (d > 180) - d -= 360; - else if (d < -180) - d += 360; - cl.viewangles[j] = cl.mviewangles[1][j] + frac*d; - } - } - - bobjrotate = anglemod(100*cl.time); - -// start on the entity after the world - for (i=1,ent=cl_entities+1 ; imodel) - { // empty slot - if (ent->forcelink) - R_RemoveEfrags (ent); // just became empty - continue; - } - -// if the object wasn't included in the last packet, remove it - if (ent->msgtime != cl.mtime[0]) - { - ent->model = NULL; - continue; - } - - VectorCopy (ent->origin, oldorg); - - if (ent->forcelink) - { // the entity was not updated in the last message - // so move to the final spot - VectorCopy (ent->msg_origins[0], ent->origin); - VectorCopy (ent->msg_angles[0], ent->angles); - } - else - { // if the delta is large, assume a teleport and don't lerp - f = frac; - for (j=0 ; j<3 ; j++) - { - delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; - if (delta[j] > 100 || delta[j] < -100) - f = 1; // assume a teleportation, not a motion - } - - // interpolate the origin and angles - for (j=0 ; j<3 ; j++) - { - ent->origin[j] = ent->msg_origins[1][j] + f*delta[j]; - - d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; - if (d > 180) - d -= 360; - else if (d < -180) - d += 360; - ent->angles[j] = ent->msg_angles[1][j] + f*d; - } - - } - -// rotate binary objects locally - if (ent->model->flags & EF_ROTATE) - ent->angles[1] = bobjrotate; - - if (ent->effects & EF_BRIGHTFIELD) - R_EntityParticles (ent); -#ifdef QUAKE2 - if (ent->effects & EF_DARKFIELD) - R_DarkFieldParticles (ent); -#endif - if (ent->effects & EF_MUZZLEFLASH) - { - vec3_t fv, rv, uv; - - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->origin[2] += 16; - AngleVectors (ent->angles, fv, rv, uv); - - VectorMA (dl->origin, 18, fv, dl->origin); - dl->radius = 200 + (rand()&31); - dl->minlight = 32; - dl->die = cl.time + 0.1; - } - if (ent->effects & EF_BRIGHTLIGHT) - { - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->origin[2] += 16; - dl->radius = 400 + (rand()&31); - dl->die = cl.time + 0.001; - } - if (ent->effects & EF_DIMLIGHT) - { - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->radius = 200 + (rand()&31); - dl->die = cl.time + 0.001; - } -#ifdef QUAKE2 - if (ent->effects & EF_DARKLIGHT) - { - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->radius = 200.0 + (rand()&31); - dl->die = cl.time + 0.001; - dl->dark = true; - } - if (ent->effects & EF_LIGHT) - { - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->radius = 200; - dl->die = cl.time + 0.001; - } -#endif - - if (ent->model->flags & EF_GIB) - R_RocketTrail (oldorg, ent->origin, 2); - else if (ent->model->flags & EF_ZOMGIB) - R_RocketTrail (oldorg, ent->origin, 4); - else if (ent->model->flags & EF_TRACER) - R_RocketTrail (oldorg, ent->origin, 3); - else if (ent->model->flags & EF_TRACER2) - R_RocketTrail (oldorg, ent->origin, 5); - else if (ent->model->flags & EF_ROCKET) - { - R_RocketTrail (oldorg, ent->origin, 0); - dl = CL_AllocDlight (i); - VectorCopy (ent->origin, dl->origin); - dl->radius = 200; - dl->die = cl.time + 0.01; - } - else if (ent->model->flags & EF_GRENADE) - R_RocketTrail (oldorg, ent->origin, 1); - else if (ent->model->flags & EF_TRACER3) - R_RocketTrail (oldorg, ent->origin, 6); - - ent->forcelink = false; - - if (i == cl.viewentity && !chase_active.value) - continue; - -#ifdef QUAKE2 - if ( ent->effects & EF_NODRAW ) - continue; -#endif - if (cl_numvisedicts < MAX_VISEDICTS) - { - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; - } - } - -} - - -/* -=============== -CL_ReadFromServer - -Read all incoming data from the server -=============== -*/ -int CL_ReadFromServer (void) -{ - int ret; - - cl.oldtime = cl.time; - cl.time += host_frametime; - - do - { - ret = CL_GetMessage (); - if (ret == -1) - Host_Error ("CL_ReadFromServer: lost server connection"); - if (!ret) - break; - - cl.last_received_message = realtime; - CL_ParseServerMessage (); - } while (ret && cls.state == ca_connected); - - if (cl_shownet.value) - Con_Printf ("\n"); - - CL_RelinkEntities (); - CL_UpdateTEnts (); - -// -// bring the links up to date -// - return 0; -} - -/* -================= -CL_SendCmd -================= -*/ -void CL_SendCmd (void) -{ - usercmd_t cmd; - - if (cls.state != ca_connected) - return; - - if (cls.signon == SIGNONS) - { - // get basic movement from keyboard - CL_BaseMove (&cmd); - - // allow mice or other external controllers to add to the move - IN_Move (&cmd); - - // send the unreliable message - CL_SendMove (&cmd); - - } - - if (cls.demoplayback) - { - SZ_Clear (&cls.message); - return; - } - -// send the reliable message - if (!cls.message.cursize) - return; // no message at all - - if (!NET_CanSendMessage (cls.netcon)) - { - Con_DPrintf ("CL_WriteToServer: can't send\n"); - return; - } - - if (NET_SendMessage (cls.netcon, &cls.message) == -1) - Host_Error ("CL_WriteToServer: lost server connection"); - - SZ_Clear (&cls.message); -} - -/* -================= -CL_Init -================= -*/ -void CL_Init (void) -{ - SZ_Alloc (&cls.message, 1024); - - CL_InitInput (); - CL_InitTEnts (); - -// -// register our commands -// - Cvar_RegisterVariable (&cl_name); - Cvar_RegisterVariable (&cl_color); - Cvar_RegisterVariable (&cl_upspeed); - Cvar_RegisterVariable (&cl_forwardspeed); - Cvar_RegisterVariable (&cl_backspeed); - Cvar_RegisterVariable (&cl_sidespeed); - Cvar_RegisterVariable (&cl_movespeedkey); - Cvar_RegisterVariable (&cl_yawspeed); - Cvar_RegisterVariable (&cl_pitchspeed); - Cvar_RegisterVariable (&cl_anglespeedkey); - Cvar_RegisterVariable (&cl_shownet); - Cvar_RegisterVariable (&cl_nolerp); - Cvar_RegisterVariable (&lookspring); - Cvar_RegisterVariable (&lookstrafe); - Cvar_RegisterVariable (&sensitivity); - - Cvar_RegisterVariable (&m_pitch); - Cvar_RegisterVariable (&m_yaw); - Cvar_RegisterVariable (&m_forward); - Cvar_RegisterVariable (&m_side); - -// Cvar_RegisterVariable (&cl_autofire); - - Cmd_AddCommand ("entities", CL_PrintEntities_f); - Cmd_AddCommand ("disconnect", CL_Disconnect_f); - Cmd_AddCommand ("record", CL_Record_f); - Cmd_AddCommand ("stop", CL_Stop_f); - Cmd_AddCommand ("playdemo", CL_PlayDemo_f); - Cmd_AddCommand ("timedemo", CL_TimeDemo_f); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cl_main.c -- client main loop + +#include "quakedef.h" + +// we need to declare some mouse variables here, because the menu system +// references them even when on a unix system. + +// these two are not intended to be set directly +cvar_t cl_name = {"_cl_name", "player", true}; +cvar_t cl_color = {"_cl_color", "0", true}; + +cvar_t cl_shownet = {"cl_shownet","0"}; // can be 0, 1, or 2 +cvar_t cl_nolerp = {"cl_nolerp","0"}; + +cvar_t lookspring = {"lookspring","0", true}; +cvar_t lookstrafe = {"lookstrafe","0", true}; +cvar_t sensitivity = {"sensitivity","3", true}; + +cvar_t m_pitch = {"m_pitch","0.022", true}; +cvar_t m_yaw = {"m_yaw","0.022", true}; +cvar_t m_forward = {"m_forward","1", true}; +cvar_t m_side = {"m_side","0.8", true}; + + +client_static_t cls; +client_state_t cl; +// FIXME: put these on hunk? +efrag_t cl_efrags[MAX_EFRAGS]; +entity_t cl_entities[MAX_EDICTS]; +entity_t cl_static_entities[MAX_STATIC_ENTITIES]; +lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; +dlight_t cl_dlights[MAX_DLIGHTS]; + +int cl_numvisedicts; +entity_t *cl_visedicts[MAX_VISEDICTS]; + +/* +===================== +CL_ClearState + +===================== +*/ +void CL_ClearState (void) +{ + int i; + + if (!sv.active) + Host_ClearMemory (); + +// wipe the entire cl structure + memset (&cl, 0, sizeof(cl)); + + SZ_Clear (&cls.message); + +// clear other arrays + memset (cl_efrags, 0, sizeof(cl_efrags)); + memset (cl_entities, 0, sizeof(cl_entities)); + memset (cl_dlights, 0, sizeof(cl_dlights)); + memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); + memset (cl_temp_entities, 0, sizeof(cl_temp_entities)); + memset (cl_beams, 0, sizeof(cl_beams)); + +// +// allocate the efrags and chain together into a free list +// + cl.free_efrags = cl_efrags; + for (i=0 ; i>4, ((int)cl_color.value)&15)); + + MSG_WriteByte (&cls.message, clc_stringcmd); + sprintf (str, "spawn %s", cls.spawnparms); + MSG_WriteString (&cls.message, str); + break; + + case 3: + MSG_WriteByte (&cls.message, clc_stringcmd); + MSG_WriteString (&cls.message, "begin"); + Cache_Report (); // print remaining memory + break; + + case 4: + SCR_EndLoadingPlaque (); // allow normal screen updates + break; + } +} + +/* +===================== +CL_NextDemo + +Called to play the next demo in the demo loop +===================== +*/ +void CL_NextDemo (void) +{ + char str[1024]; + + if (cls.demonum == -1) + return; // don't play demos + + SCR_BeginLoadingPlaque (); + + if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) + { + cls.demonum = 0; + if (!cls.demos[cls.demonum][0]) + { + Con_Printf ("No demos listed with startdemos\n"); + cls.demonum = -1; + return; + } + } + + sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]); + Cbuf_InsertText (str); + cls.demonum++; +} + +/* +============== +CL_PrintEntities_f +============== +*/ +void CL_PrintEntities_f (void) +{ + entity_t *ent; + int i; + + for (i=0,ent=cl_entities ; imodel) + { + Con_Printf ("EMPTY\n"); + continue; + } + Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n" + ,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]); + } +} + + +/* +=============== +SetPal + +Debugging tool, just flashes the screen +=============== +*/ +void SetPal (int i) +{ +#if 0 + static int old; + byte pal[768]; + int c; + + if (i == old) + return; + old = i; + + if (i==0) + VID_SetPalette (host_basepal); + else if (i==1) + { + for (c=0 ; c<768 ; c+=3) + { + pal[c] = 0; + pal[c+1] = 255; + pal[c+2] = 0; + } + VID_SetPalette (pal); + } + else + { + for (c=0 ; c<768 ; c+=3) + { + pal[c] = 0; + pal[c+1] = 0; + pal[c+2] = 255; + } + VID_SetPalette (pal); + } +#endif +} + +/* +=============== +CL_AllocDlight + +=============== +*/ +dlight_t *CL_AllocDlight (int key) +{ + int i; + dlight_t *dl; + +// first look for an exact key match + if (key) + { + dl = cl_dlights; + for (i=0 ; ikey == key) + { + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; + } + } + } + +// then look for anything else + dl = cl_dlights; + for (i=0 ; idie < cl.time) + { + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; + } + } + + dl = &cl_dlights[0]; + memset (dl, 0, sizeof(*dl)); + dl->key = key; + return dl; +} + + +/* +=============== +CL_DecayLights + +=============== +*/ +void CL_DecayLights (void) +{ + int i; + dlight_t *dl; + float time; + + time = cl.time - cl.oldtime; + + dl = cl_dlights; + for (i=0 ; idie < cl.time || !dl->radius) + continue; + + dl->radius -= time*dl->decay; + if (dl->radius < 0) + dl->radius = 0; + } +} + + +/* +=============== +CL_LerpPoint + +Determines the fraction between the last two messages that the objects +should be put at. +=============== +*/ +float CL_LerpPoint (void) +{ + float f, frac; + + f = cl.mtime[0] - cl.mtime[1]; + + if (!f || cl_nolerp.value || cls.timedemo || sv.active) + { + cl.time = cl.mtime[0]; + return 1; + } + + if (f > 0.1) + { // dropped packet, or start of demo + cl.mtime[1] = cl.mtime[0] - 0.1; + f = 0.1; + } + frac = (cl.time - cl.mtime[1]) / f; +//Con_Printf ("frac: %f\n",frac); + if (frac < 0) + { + if (frac < -0.01) + { +SetPal(1); + cl.time = cl.mtime[1]; +// Con_Printf ("low frac\n"); + } + frac = 0; + } + else if (frac > 1) + { + if (frac > 1.01) + { +SetPal(2); + cl.time = cl.mtime[0]; +// Con_Printf ("high frac\n"); + } + frac = 1; + } + else + SetPal(0); + + return frac; +} + + +/* +=============== +CL_RelinkEntities +=============== +*/ +void CL_RelinkEntities (void) +{ + entity_t *ent; + int i, j; + float frac, f, d; + vec3_t delta; + float bobjrotate; + vec3_t oldorg; + dlight_t *dl; + +// determine partial update time + frac = CL_LerpPoint (); + + cl_numvisedicts = 0; + +// +// interpolate player info +// + for (i=0 ; i<3 ; i++) + cl.velocity[i] = cl.mvelocity[1][i] + + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); + + if (cls.demoplayback) + { + // interpolate the angles + for (j=0 ; j<3 ; j++) + { + d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; + if (d > 180) + d -= 360; + else if (d < -180) + d += 360; + cl.viewangles[j] = cl.mviewangles[1][j] + frac*d; + } + } + + bobjrotate = anglemod(100*cl.time); + +// start on the entity after the world + for (i=1,ent=cl_entities+1 ; imodel) + { // empty slot + if (ent->forcelink) + R_RemoveEfrags (ent); // just became empty + continue; + } + +// if the object wasn't included in the last packet, remove it + if (ent->msgtime != cl.mtime[0]) + { + ent->model = NULL; + continue; + } + + VectorCopy (ent->origin, oldorg); + + if (ent->forcelink) + { // the entity was not updated in the last message + // so move to the final spot + VectorCopy (ent->msg_origins[0], ent->origin); + VectorCopy (ent->msg_angles[0], ent->angles); + } + else + { // if the delta is large, assume a teleport and don't lerp + f = frac; + for (j=0 ; j<3 ; j++) + { + delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; + if (delta[j] > 100 || delta[j] < -100) + f = 1; // assume a teleportation, not a motion + } + + // interpolate the origin and angles + for (j=0 ; j<3 ; j++) + { + ent->origin[j] = ent->msg_origins[1][j] + f*delta[j]; + + d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; + if (d > 180) + d -= 360; + else if (d < -180) + d += 360; + ent->angles[j] = ent->msg_angles[1][j] + f*d; + } + + } + +// rotate binary objects locally + if (ent->model->flags & EF_ROTATE) + ent->angles[1] = bobjrotate; + + if (ent->effects & EF_BRIGHTFIELD) + R_EntityParticles (ent); +#ifdef QUAKE2 + if (ent->effects & EF_DARKFIELD) + R_DarkFieldParticles (ent); +#endif + if (ent->effects & EF_MUZZLEFLASH) + { + vec3_t fv, rv, uv; + + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->origin[2] += 16; + AngleVectors (ent->angles, fv, rv, uv); + + VectorMA (dl->origin, 18, fv, dl->origin); + dl->radius = 200 + (rand()&31); + dl->minlight = 32; + dl->die = cl.time + 0.1; + } + if (ent->effects & EF_BRIGHTLIGHT) + { + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->origin[2] += 16; + dl->radius = 400 + (rand()&31); + dl->die = cl.time + 0.001; + } + if (ent->effects & EF_DIMLIGHT) + { + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200 + (rand()&31); + dl->die = cl.time + 0.001; + } +#ifdef QUAKE2 + if (ent->effects & EF_DARKLIGHT) + { + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200.0 + (rand()&31); + dl->die = cl.time + 0.001; + dl->dark = true; + } + if (ent->effects & EF_LIGHT) + { + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200; + dl->die = cl.time + 0.001; + } +#endif + + if (ent->model->flags & EF_GIB) + R_RocketTrail (oldorg, ent->origin, 2); + else if (ent->model->flags & EF_ZOMGIB) + R_RocketTrail (oldorg, ent->origin, 4); + else if (ent->model->flags & EF_TRACER) + R_RocketTrail (oldorg, ent->origin, 3); + else if (ent->model->flags & EF_TRACER2) + R_RocketTrail (oldorg, ent->origin, 5); + else if (ent->model->flags & EF_ROCKET) + { + R_RocketTrail (oldorg, ent->origin, 0); + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200; + dl->die = cl.time + 0.01; + } + else if (ent->model->flags & EF_GRENADE) + R_RocketTrail (oldorg, ent->origin, 1); + else if (ent->model->flags & EF_TRACER3) + R_RocketTrail (oldorg, ent->origin, 6); + + ent->forcelink = false; + + if (i == cl.viewentity && !chase_active.value) + continue; + +#ifdef QUAKE2 + if ( ent->effects & EF_NODRAW ) + continue; +#endif + if (cl_numvisedicts < MAX_VISEDICTS) + { + cl_visedicts[cl_numvisedicts] = ent; + cl_numvisedicts++; + } + } + +} + + +/* +=============== +CL_ReadFromServer + +Read all incoming data from the server +=============== +*/ +int CL_ReadFromServer (void) +{ + int ret; + + cl.oldtime = cl.time; + cl.time += host_frametime; + + do + { + ret = CL_GetMessage (); + if (ret == -1) + Host_Error ("CL_ReadFromServer: lost server connection"); + if (!ret) + break; + + cl.last_received_message = realtime; + CL_ParseServerMessage (); + } while (ret && cls.state == ca_connected); + + if (cl_shownet.value) + Con_Printf ("\n"); + + CL_RelinkEntities (); + CL_UpdateTEnts (); + +// +// bring the links up to date +// + return 0; +} + +/* +================= +CL_SendCmd +================= +*/ +void CL_SendCmd (void) +{ + usercmd_t cmd; + + if (cls.state != ca_connected) + return; + + if (cls.signon == SIGNONS) + { + // get basic movement from keyboard + CL_BaseMove (&cmd); + + // allow mice or other external controllers to add to the move + IN_Move (&cmd); + + // send the unreliable message + CL_SendMove (&cmd); + + } + + if (cls.demoplayback) + { + SZ_Clear (&cls.message); + return; + } + +// send the reliable message + if (!cls.message.cursize) + return; // no message at all + + if (!NET_CanSendMessage (cls.netcon)) + { + Con_DPrintf ("CL_WriteToServer: can't send\n"); + return; + } + + if (NET_SendMessage (cls.netcon, &cls.message) == -1) + Host_Error ("CL_WriteToServer: lost server connection"); + + SZ_Clear (&cls.message); +} + +/* +================= +CL_Init +================= +*/ +void CL_Init (void) +{ + SZ_Alloc (&cls.message, 1024); + + CL_InitInput (); + CL_InitTEnts (); + +// +// register our commands +// + Cvar_RegisterVariable (&cl_name); + Cvar_RegisterVariable (&cl_color); + Cvar_RegisterVariable (&cl_upspeed); + Cvar_RegisterVariable (&cl_forwardspeed); + Cvar_RegisterVariable (&cl_backspeed); + Cvar_RegisterVariable (&cl_sidespeed); + Cvar_RegisterVariable (&cl_movespeedkey); + Cvar_RegisterVariable (&cl_yawspeed); + Cvar_RegisterVariable (&cl_pitchspeed); + Cvar_RegisterVariable (&cl_anglespeedkey); + Cvar_RegisterVariable (&cl_shownet); + Cvar_RegisterVariable (&cl_nolerp); + Cvar_RegisterVariable (&lookspring); + Cvar_RegisterVariable (&lookstrafe); + Cvar_RegisterVariable (&sensitivity); + + Cvar_RegisterVariable (&m_pitch); + Cvar_RegisterVariable (&m_yaw); + Cvar_RegisterVariable (&m_forward); + Cvar_RegisterVariable (&m_side); + +// Cvar_RegisterVariable (&cl_autofire); + + Cmd_AddCommand ("entities", CL_PrintEntities_f); + Cmd_AddCommand ("disconnect", CL_Disconnect_f); + Cmd_AddCommand ("record", CL_Record_f); + Cmd_AddCommand ("stop", CL_Stop_f); + Cmd_AddCommand ("playdemo", CL_PlayDemo_f); + Cmd_AddCommand ("timedemo", CL_TimeDemo_f); +} + diff --git a/WinQuake/cl_parse.c b/WinQuake/cl_parse.c index c79ca47..528c254 100644 --- a/WinQuake/cl_parse.c +++ b/WinQuake/cl_parse.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // cl_parse.c -- parse a message received from the server #include "quakedef.h" diff --git a/WinQuake/cl_tent.c b/WinQuake/cl_tent.c index 546e832..4565fd0 100644 --- a/WinQuake/cl_tent.c +++ b/WinQuake/cl_tent.c @@ -1,394 +1,394 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cl_tent.c -- client side temporary entities - -#include "quakedef.h" - -int num_temp_entities; -entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; -beam_t cl_beams[MAX_BEAMS]; - -sfx_t *cl_sfx_wizhit; -sfx_t *cl_sfx_knighthit; -sfx_t *cl_sfx_tink1; -sfx_t *cl_sfx_ric1; -sfx_t *cl_sfx_ric2; -sfx_t *cl_sfx_ric3; -sfx_t *cl_sfx_r_exp3; -#ifdef QUAKE2 -sfx_t *cl_sfx_imp; -sfx_t *cl_sfx_rail; -#endif - -/* -================= -CL_ParseTEnt -================= -*/ -void CL_InitTEnts (void) -{ - cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); - cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); - cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); - cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); - cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); - cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); - cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); -#ifdef QUAKE2 - cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav"); - cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav"); -#endif -} - -/* -================= -CL_ParseBeam -================= -*/ -void CL_ParseBeam (model_t *m) -{ - int ent; - vec3_t start, end; - beam_t *b; - int i; - - ent = MSG_ReadShort (); - - start[0] = MSG_ReadCoord (); - start[1] = MSG_ReadCoord (); - start[2] = MSG_ReadCoord (); - - end[0] = MSG_ReadCoord (); - end[1] = MSG_ReadCoord (); - end[2] = MSG_ReadCoord (); - -// override any beam with the same entity - for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) - if (b->entity == ent) - { - b->entity = ent; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - -// find a free beam - for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) - { - if (!b->model || b->endtime < cl.time) - { - b->entity = ent; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - } - Con_Printf ("beam list overflow!\n"); -} - -/* -================= -CL_ParseTEnt -================= -*/ -void CL_ParseTEnt (void) -{ - int type; - vec3_t pos; -#ifdef QUAKE2 - vec3_t endpos; -#endif - dlight_t *dl; - int rnd; - int colorStart, colorLength; - - type = MSG_ReadByte (); - switch (type) - { - case TE_WIZSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 20, 30); - S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); - break; - - case TE_KNIGHTSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 226, 20); - S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); - break; - - case TE_SPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); -#ifdef GLTEST - Test_Spawn (pos); -#else - R_RunParticleEffect (pos, vec3_origin, 0, 10); -#endif - if ( rand() % 5 ) - S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); - else - { - rnd = rand() & 3; - if (rnd == 1) - S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); - else if (rnd == 2) - S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); - else - S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); - } - break; - case TE_SUPERSPIKE: // super spike hitting wall - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 0, 20); - - if ( rand() % 5 ) - S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); - else - { - rnd = rand() & 3; - if (rnd == 1) - S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); - else if (rnd == 2) - S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); - else - S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); - } - break; - - case TE_GUNSHOT: // bullet hitting wall - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_RunParticleEffect (pos, vec3_origin, 0, 20); - break; - - case TE_EXPLOSION: // rocket explosion - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_ParticleExplosion (pos); - dl = CL_AllocDlight (0); - VectorCopy (pos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - break; - - case TE_TAREXPLOSION: // tarbaby explosion - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_BlobExplosion (pos); - - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - break; - - case TE_LIGHTNING1: // lightning bolts - CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); - break; - - case TE_LIGHTNING2: // lightning bolts - CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true)); - break; - - case TE_LIGHTNING3: // lightning bolts - CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true)); - break; - -// PGM 01/21/97 - case TE_BEAM: // grappling hook beam - CL_ParseBeam (Mod_ForName("progs/beam.mdl", true)); - break; -// PGM 01/21/97 - - case TE_LAVASPLASH: - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_LavaSplash (pos); - break; - - case TE_TELEPORT: - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - R_TeleportSplash (pos); - break; - - case TE_EXPLOSION2: // color mapped explosion - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - colorStart = MSG_ReadByte (); - colorLength = MSG_ReadByte (); - R_ParticleExplosion2 (pos, colorStart, colorLength); - dl = CL_AllocDlight (0); - VectorCopy (pos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - break; - -#ifdef QUAKE2 - case TE_IMPLOSION: - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); - break; - - case TE_RAILTRAIL: - pos[0] = MSG_ReadCoord (); - pos[1] = MSG_ReadCoord (); - pos[2] = MSG_ReadCoord (); - endpos[0] = MSG_ReadCoord (); - endpos[1] = MSG_ReadCoord (); - endpos[2] = MSG_ReadCoord (); - S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); - S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); - R_RocketTrail (pos, endpos, 0+128); - R_ParticleExplosion (endpos); - dl = CL_AllocDlight (-1); - VectorCopy (endpos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - break; -#endif - - default: - Sys_Error ("CL_ParseTEnt: bad type"); - } -} - - -/* -================= -CL_NewTempEntity -================= -*/ -entity_t *CL_NewTempEntity (void) -{ - entity_t *ent; - - if (cl_numvisedicts == MAX_VISEDICTS) - return NULL; - if (num_temp_entities == MAX_TEMP_ENTITIES) - return NULL; - ent = &cl_temp_entities[num_temp_entities]; - memset (ent, 0, sizeof(*ent)); - num_temp_entities++; - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; - - ent->colormap = vid.colormap; - return ent; -} - - -/* -================= -CL_UpdateTEnts -================= -*/ -void CL_UpdateTEnts (void) -{ - int i; - beam_t *b; - vec3_t dist, org; - float d; - entity_t *ent; - float yaw, pitch; - float forward; - - num_temp_entities = 0; - -// update lightning - for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) - { - if (!b->model || b->endtime < cl.time) - continue; - - // if coming from the player, update the start position - if (b->entity == cl.viewentity) - { - VectorCopy (cl_entities[cl.viewentity].origin, b->start); - } - - // calculate pitch and yaw - VectorSubtract (b->end, b->start, dist); - - if (dist[1] == 0 && dist[0] == 0) - { - yaw = 0; - if (dist[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); - pitch = (int) (atan2(dist[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - // add new entities for the lightning - VectorCopy (b->start, org); - d = VectorNormalize(dist); - while (d > 0) - { - ent = CL_NewTempEntity (); - if (!ent) - return; - VectorCopy (org, ent->origin); - ent->model = b->model; - ent->angles[0] = pitch; - ent->angles[1] = yaw; - ent->angles[2] = rand()%360; - - for (i=0 ; i<3 ; i++) - org[i] += dist[i]*30; - d -= 30; - } - } - -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cl_tent.c -- client side temporary entities + +#include "quakedef.h" + +int num_temp_entities; +entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; +beam_t cl_beams[MAX_BEAMS]; + +sfx_t *cl_sfx_wizhit; +sfx_t *cl_sfx_knighthit; +sfx_t *cl_sfx_tink1; +sfx_t *cl_sfx_ric1; +sfx_t *cl_sfx_ric2; +sfx_t *cl_sfx_ric3; +sfx_t *cl_sfx_r_exp3; +#ifdef QUAKE2 +sfx_t *cl_sfx_imp; +sfx_t *cl_sfx_rail; +#endif + +/* +================= +CL_ParseTEnt +================= +*/ +void CL_InitTEnts (void) +{ + cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); + cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); + cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); + cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); + cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); + cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); + cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); +#ifdef QUAKE2 + cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav"); + cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav"); +#endif +} + +/* +================= +CL_ParseBeam +================= +*/ +void CL_ParseBeam (model_t *m) +{ + int ent; + vec3_t start, end; + beam_t *b; + int i; + + ent = MSG_ReadShort (); + + start[0] = MSG_ReadCoord (); + start[1] = MSG_ReadCoord (); + start[2] = MSG_ReadCoord (); + + end[0] = MSG_ReadCoord (); + end[1] = MSG_ReadCoord (); + end[2] = MSG_ReadCoord (); + +// override any beam with the same entity + for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) + if (b->entity == ent) + { + b->entity = ent; + b->model = m; + b->endtime = cl.time + 0.2; + VectorCopy (start, b->start); + VectorCopy (end, b->end); + return; + } + +// find a free beam + for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) + { + if (!b->model || b->endtime < cl.time) + { + b->entity = ent; + b->model = m; + b->endtime = cl.time + 0.2; + VectorCopy (start, b->start); + VectorCopy (end, b->end); + return; + } + } + Con_Printf ("beam list overflow!\n"); +} + +/* +================= +CL_ParseTEnt +================= +*/ +void CL_ParseTEnt (void) +{ + int type; + vec3_t pos; +#ifdef QUAKE2 + vec3_t endpos; +#endif + dlight_t *dl; + int rnd; + int colorStart, colorLength; + + type = MSG_ReadByte (); + switch (type) + { + case TE_WIZSPIKE: // spike hitting wall + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 20, 30); + S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); + break; + + case TE_KNIGHTSPIKE: // spike hitting wall + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 226, 20); + S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); + break; + + case TE_SPIKE: // spike hitting wall + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); +#ifdef GLTEST + Test_Spawn (pos); +#else + R_RunParticleEffect (pos, vec3_origin, 0, 10); +#endif + if ( rand() % 5 ) + S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); + else + { + rnd = rand() & 3; + if (rnd == 1) + S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); + else if (rnd == 2) + S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); + else + S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); + } + break; + case TE_SUPERSPIKE: // super spike hitting wall + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 0, 20); + + if ( rand() % 5 ) + S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); + else + { + rnd = rand() & 3; + if (rnd == 1) + S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); + else if (rnd == 2) + S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); + else + S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); + } + break; + + case TE_GUNSHOT: // bullet hitting wall + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_RunParticleEffect (pos, vec3_origin, 0, 20); + break; + + case TE_EXPLOSION: // rocket explosion + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_ParticleExplosion (pos); + dl = CL_AllocDlight (0); + VectorCopy (pos, dl->origin); + dl->radius = 350; + dl->die = cl.time + 0.5; + dl->decay = 300; + S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + break; + + case TE_TAREXPLOSION: // tarbaby explosion + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_BlobExplosion (pos); + + S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + break; + + case TE_LIGHTNING1: // lightning bolts + CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); + break; + + case TE_LIGHTNING2: // lightning bolts + CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true)); + break; + + case TE_LIGHTNING3: // lightning bolts + CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true)); + break; + +// PGM 01/21/97 + case TE_BEAM: // grappling hook beam + CL_ParseBeam (Mod_ForName("progs/beam.mdl", true)); + break; +// PGM 01/21/97 + + case TE_LAVASPLASH: + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_LavaSplash (pos); + break; + + case TE_TELEPORT: + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + R_TeleportSplash (pos); + break; + + case TE_EXPLOSION2: // color mapped explosion + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + colorStart = MSG_ReadByte (); + colorLength = MSG_ReadByte (); + R_ParticleExplosion2 (pos, colorStart, colorLength); + dl = CL_AllocDlight (0); + VectorCopy (pos, dl->origin); + dl->radius = 350; + dl->die = cl.time + 0.5; + dl->decay = 300; + S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + break; + +#ifdef QUAKE2 + case TE_IMPLOSION: + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); + break; + + case TE_RAILTRAIL: + pos[0] = MSG_ReadCoord (); + pos[1] = MSG_ReadCoord (); + pos[2] = MSG_ReadCoord (); + endpos[0] = MSG_ReadCoord (); + endpos[1] = MSG_ReadCoord (); + endpos[2] = MSG_ReadCoord (); + S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); + S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); + R_RocketTrail (pos, endpos, 0+128); + R_ParticleExplosion (endpos); + dl = CL_AllocDlight (-1); + VectorCopy (endpos, dl->origin); + dl->radius = 350; + dl->die = cl.time + 0.5; + dl->decay = 300; + break; +#endif + + default: + Sys_Error ("CL_ParseTEnt: bad type"); + } +} + + +/* +================= +CL_NewTempEntity +================= +*/ +entity_t *CL_NewTempEntity (void) +{ + entity_t *ent; + + if (cl_numvisedicts == MAX_VISEDICTS) + return NULL; + if (num_temp_entities == MAX_TEMP_ENTITIES) + return NULL; + ent = &cl_temp_entities[num_temp_entities]; + memset (ent, 0, sizeof(*ent)); + num_temp_entities++; + cl_visedicts[cl_numvisedicts] = ent; + cl_numvisedicts++; + + ent->colormap = vid.colormap; + return ent; +} + + +/* +================= +CL_UpdateTEnts +================= +*/ +void CL_UpdateTEnts (void) +{ + int i; + beam_t *b; + vec3_t dist, org; + float d; + entity_t *ent; + float yaw, pitch; + float forward; + + num_temp_entities = 0; + +// update lightning + for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) + { + if (!b->model || b->endtime < cl.time) + continue; + + // if coming from the player, update the start position + if (b->entity == cl.viewentity) + { + VectorCopy (cl_entities[cl.viewentity].origin, b->start); + } + + // calculate pitch and yaw + VectorSubtract (b->end, b->start, dist); + + if (dist[1] == 0 && dist[0] == 0) + { + yaw = 0; + if (dist[2] > 0) + pitch = 90; + else + pitch = 270; + } + else + { + yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + + forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); + pitch = (int) (atan2(dist[2], forward) * 180 / M_PI); + if (pitch < 0) + pitch += 360; + } + + // add new entities for the lightning + VectorCopy (b->start, org); + d = VectorNormalize(dist); + while (d > 0) + { + ent = CL_NewTempEntity (); + if (!ent) + return; + VectorCopy (org, ent->origin); + ent->model = b->model; + ent->angles[0] = pitch; + ent->angles[1] = yaw; + ent->angles[2] = rand()%360; + + for (i=0 ; i<3 ; i++) + org[i] += dist[i]*30; + d -= 30; + } + } + +} + + diff --git a/WinQuake/clean.bat b/WinQuake/clean.bat index 8a5aad4..92ed629 100644 --- a/WinQuake/clean.bat +++ b/WinQuake/clean.bat @@ -1,18 +1,18 @@ -rmdir /s /q debug -rmdir /s /q release -rmdir /s /q debug_gl -rmdir /s /q release_gl - -rmdir /s /q gas2masm\debug -rmdir /s /q gas2masm\release - -del gas2masm\gas2masm.opt -del gas2masm\gas2masm.plg -del gas2masm\gas2masm.ncb -del gas2masm\gas2masm.stt - -del WinQuake.opt -del WinQuake.plg -del WinQuake.ncb -del WinQuake.stt - +rmdir /s /q debug +rmdir /s /q release +rmdir /s /q debug_gl +rmdir /s /q release_gl + +rmdir /s /q gas2masm\debug +rmdir /s /q gas2masm\release + +del gas2masm\gas2masm.opt +del gas2masm\gas2masm.plg +del gas2masm\gas2masm.ncb +del gas2masm\gas2masm.stt + +del WinQuake.opt +del WinQuake.plg +del WinQuake.ncb +del WinQuake.stt + diff --git a/WinQuake/client.h b/WinQuake/client.h index 7c59ee9..2da1c67 100644 --- a/WinQuake/client.h +++ b/WinQuake/client.h @@ -1,375 +1,375 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// client.h - -typedef struct -{ - vec3_t viewangles; - -// intended velocities - float forwardmove; - float sidemove; - float upmove; -#ifdef QUAKE2 - byte lightlevel; -#endif -} usercmd_t; - -typedef struct -{ - int length; - char map[MAX_STYLESTRING]; -} lightstyle_t; - -typedef struct -{ - char name[MAX_SCOREBOARDNAME]; - float entertime; - int frags; - int colors; // two 4 bit fields - byte translations[VID_GRADES*256]; -} scoreboard_t; - -typedef struct -{ - int destcolor[3]; - int percent; // 0-256 -} cshift_t; - -#define CSHIFT_CONTENTS 0 -#define CSHIFT_DAMAGE 1 -#define CSHIFT_BONUS 2 -#define CSHIFT_POWERUP 3 -#define NUM_CSHIFTS 4 - -#define NAME_LENGTH 64 - - -// -// client_state_t should hold all pieces of the client state -// - -#define SIGNONS 4 // signon messages to receive before connected - -#define MAX_DLIGHTS 32 -typedef struct -{ - vec3_t origin; - float radius; - float die; // stop lighting after this time - float decay; // drop this each second - float minlight; // don't add when contributing less - int key; -#ifdef QUAKE2 - qboolean dark; // subtracts light instead of adding -#endif -} dlight_t; - - -#define MAX_BEAMS 24 -typedef struct -{ - int entity; - struct model_s *model; - float endtime; - vec3_t start, end; -} beam_t; - -#define MAX_EFRAGS 640 - -#define MAX_MAPSTRING 2048 -#define MAX_DEMOS 8 -#define MAX_DEMONAME 16 - -typedef enum { -ca_dedicated, // a dedicated server with no ability to start a client -ca_disconnected, // full screen console with no connection -ca_connected // valid netcon, talking to a server -} cactive_t; - -// -// the client_static_t structure is persistant through an arbitrary number -// of server connections -// -typedef struct -{ - cactive_t state; - -// personalization data sent to server - char mapstring[MAX_QPATH]; - char spawnparms[MAX_MAPSTRING]; // to restart a level - -// demo loop control - int demonum; // -1 = don't play demos - char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing - -// demo recording info must be here, because record is started before -// entering a map (and clearing client_state_t) - qboolean demorecording; - qboolean demoplayback; - qboolean timedemo; - int forcetrack; // -1 = use normal cd track - FILE *demofile; - int td_lastframe; // to meter out one message a frame - int td_startframe; // host_framecount at start - float td_starttime; // realtime at second frame of timedemo - - -// connection information - int signon; // 0 to SIGNONS - struct qsocket_s *netcon; - sizebuf_t message; // writing buffer to send to server - -} client_static_t; - -extern client_static_t cls; - -// -// the client_state_t structure is wiped completely at every -// server signon -// -typedef struct -{ - int movemessages; // since connecting to this server - // throw out the first couple, so the player - // doesn't accidentally do something the - // first frame - usercmd_t cmd; // last command sent to the server - -// information for local display - int stats[MAX_CL_STATS]; // health, etc - int items; // inventory bit flags - float item_gettime[32]; // cl.time of aquiring item, for blinking - float faceanimtime; // use anim frame if cl.time < this - - cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups - cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types - -// the client maintains its own idea of view angles, which are -// sent to the server each frame. The server sets punchangle when -// the view is temporarliy offset, and an angle reset commands at the start -// of each level and after teleporting. - vec3_t mviewangles[2]; // during demo playback viewangles is lerped - // between these - vec3_t viewangles; - - vec3_t mvelocity[2]; // update by server, used for lean+bob - // (0 is newest) - vec3_t velocity; // lerped between mvelocity[0] and [1] - - vec3_t punchangle; // temporary offset - -// pitch drifting vars - float idealpitch; - float pitchvel; - qboolean nodrift; - float driftmove; - double laststop; - - float viewheight; - float crouch; // local amount for smoothing stepups - - qboolean paused; // send over by server - qboolean onground; - qboolean inwater; - - int intermission; // don't change view angle, full screen, etc - int completed_time; // latched at intermission start - - double mtime[2]; // the timestamp of last two messages - double time; // clients view of time, should be between - // servertime and oldservertime to generate - // a lerp point for other data - double oldtime; // previous cl.time, time-oldtime is used - // to decay light values and smooth step ups - - - float last_received_message; // (realtime) for net trouble icon - -// -// information that is static for the entire time connected to a server -// - struct model_s *model_precache[MAX_MODELS]; - struct sfx_s *sound_precache[MAX_SOUNDS]; - - char levelname[40]; // for display on solo scoreboard - int viewentity; // cl_entitites[cl.viewentity] = player - int maxclients; - int gametype; - -// refresh related state - struct model_s *worldmodel; // cl_entitites[0].model - struct efrag_s *free_efrags; - int num_entities; // held in cl_entities array - int num_statics; // held in cl_staticentities array - entity_t viewent; // the gun model - - int cdtrack, looptrack; // cd audio - -// frag scoreboard - scoreboard_t *scores; // [cl.maxclients] - -#ifdef QUAKE2 -// light level at player's position including dlights -// this is sent back to the server each frame -// architectually ugly but it works - int light_level; -#endif -} client_state_t; - - -// -// cvars -// -extern cvar_t cl_name; -extern cvar_t cl_color; - -extern cvar_t cl_upspeed; -extern cvar_t cl_forwardspeed; -extern cvar_t cl_backspeed; -extern cvar_t cl_sidespeed; - -extern cvar_t cl_movespeedkey; - -extern cvar_t cl_yawspeed; -extern cvar_t cl_pitchspeed; - -extern cvar_t cl_anglespeedkey; - -extern cvar_t cl_autofire; - -extern cvar_t cl_shownet; -extern cvar_t cl_nolerp; - -extern cvar_t cl_pitchdriftspeed; -extern cvar_t lookspring; -extern cvar_t lookstrafe; -extern cvar_t sensitivity; - -extern cvar_t m_pitch; -extern cvar_t m_yaw; -extern cvar_t m_forward; -extern cvar_t m_side; - - -#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc -#define MAX_STATIC_ENTITIES 128 // torches, etc - -extern client_state_t cl; - -// FIXME, allocate dynamically -extern efrag_t cl_efrags[MAX_EFRAGS]; -extern entity_t cl_entities[MAX_EDICTS]; -extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -extern dlight_t cl_dlights[MAX_DLIGHTS]; -extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; -extern beam_t cl_beams[MAX_BEAMS]; - -//============================================================================= - -// -// cl_main -// -dlight_t *CL_AllocDlight (int key); -void CL_DecayLights (void); - -void CL_Init (void); - -void CL_EstablishConnection (char *host); -void CL_Signon1 (void); -void CL_Signon2 (void); -void CL_Signon3 (void); -void CL_Signon4 (void); - -void CL_Disconnect (void); -void CL_Disconnect_f (void); -void CL_NextDemo (void); - -#define MAX_VISEDICTS 256 -extern int cl_numvisedicts; -extern entity_t *cl_visedicts[MAX_VISEDICTS]; - -// -// cl_input -// -typedef struct -{ - int down[2]; // key nums holding it down - int state; // low bit is down state -} kbutton_t; - -extern kbutton_t in_mlook, in_klook; -extern kbutton_t in_strafe; -extern kbutton_t in_speed; - -void CL_InitInput (void); -void CL_SendCmd (void); -void CL_SendMove (usercmd_t *cmd); - -void CL_ParseTEnt (void); -void CL_UpdateTEnts (void); - -void CL_ClearState (void); - - -int CL_ReadFromServer (void); -void CL_WriteToServer (usercmd_t *cmd); -void CL_BaseMove (usercmd_t *cmd); - - -float CL_KeyState (kbutton_t *key); -char *Key_KeynumToString (int keynum); - -// -// cl_demo.c -// -void CL_StopPlayback (void); -int CL_GetMessage (void); - -void CL_Stop_f (void); -void CL_Record_f (void); -void CL_PlayDemo_f (void); -void CL_TimeDemo_f (void); - -// -// cl_parse.c -// -void CL_ParseServerMessage (void); -void CL_NewTranslation (int slot); - -// -// view -// -void V_StartPitchDrift (void); -void V_StopPitchDrift (void); - -void V_RenderView (void); -void V_UpdatePalette (void); -void V_Register (void); -void V_ParseDamage (void); -void V_SetContentsColor (int contents); - - -// -// cl_tent -// -void CL_InitTEnts (void); -void CL_SignonReply (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// client.h + +typedef struct +{ + vec3_t viewangles; + +// intended velocities + float forwardmove; + float sidemove; + float upmove; +#ifdef QUAKE2 + byte lightlevel; +#endif +} usercmd_t; + +typedef struct +{ + int length; + char map[MAX_STYLESTRING]; +} lightstyle_t; + +typedef struct +{ + char name[MAX_SCOREBOARDNAME]; + float entertime; + int frags; + int colors; // two 4 bit fields + byte translations[VID_GRADES*256]; +} scoreboard_t; + +typedef struct +{ + int destcolor[3]; + int percent; // 0-256 +} cshift_t; + +#define CSHIFT_CONTENTS 0 +#define CSHIFT_DAMAGE 1 +#define CSHIFT_BONUS 2 +#define CSHIFT_POWERUP 3 +#define NUM_CSHIFTS 4 + +#define NAME_LENGTH 64 + + +// +// client_state_t should hold all pieces of the client state +// + +#define SIGNONS 4 // signon messages to receive before connected + +#define MAX_DLIGHTS 32 +typedef struct +{ + vec3_t origin; + float radius; + float die; // stop lighting after this time + float decay; // drop this each second + float minlight; // don't add when contributing less + int key; +#ifdef QUAKE2 + qboolean dark; // subtracts light instead of adding +#endif +} dlight_t; + + +#define MAX_BEAMS 24 +typedef struct +{ + int entity; + struct model_s *model; + float endtime; + vec3_t start, end; +} beam_t; + +#define MAX_EFRAGS 640 + +#define MAX_MAPSTRING 2048 +#define MAX_DEMOS 8 +#define MAX_DEMONAME 16 + +typedef enum { +ca_dedicated, // a dedicated server with no ability to start a client +ca_disconnected, // full screen console with no connection +ca_connected // valid netcon, talking to a server +} cactive_t; + +// +// the client_static_t structure is persistant through an arbitrary number +// of server connections +// +typedef struct +{ + cactive_t state; + +// personalization data sent to server + char mapstring[MAX_QPATH]; + char spawnparms[MAX_MAPSTRING]; // to restart a level + +// demo loop control + int demonum; // -1 = don't play demos + char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing + +// demo recording info must be here, because record is started before +// entering a map (and clearing client_state_t) + qboolean demorecording; + qboolean demoplayback; + qboolean timedemo; + int forcetrack; // -1 = use normal cd track + FILE *demofile; + int td_lastframe; // to meter out one message a frame + int td_startframe; // host_framecount at start + float td_starttime; // realtime at second frame of timedemo + + +// connection information + int signon; // 0 to SIGNONS + struct qsocket_s *netcon; + sizebuf_t message; // writing buffer to send to server + +} client_static_t; + +extern client_static_t cls; + +// +// the client_state_t structure is wiped completely at every +// server signon +// +typedef struct +{ + int movemessages; // since connecting to this server + // throw out the first couple, so the player + // doesn't accidentally do something the + // first frame + usercmd_t cmd; // last command sent to the server + +// information for local display + int stats[MAX_CL_STATS]; // health, etc + int items; // inventory bit flags + float item_gettime[32]; // cl.time of aquiring item, for blinking + float faceanimtime; // use anim frame if cl.time < this + + cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups + cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types + +// the client maintains its own idea of view angles, which are +// sent to the server each frame. The server sets punchangle when +// the view is temporarliy offset, and an angle reset commands at the start +// of each level and after teleporting. + vec3_t mviewangles[2]; // during demo playback viewangles is lerped + // between these + vec3_t viewangles; + + vec3_t mvelocity[2]; // update by server, used for lean+bob + // (0 is newest) + vec3_t velocity; // lerped between mvelocity[0] and [1] + + vec3_t punchangle; // temporary offset + +// pitch drifting vars + float idealpitch; + float pitchvel; + qboolean nodrift; + float driftmove; + double laststop; + + float viewheight; + float crouch; // local amount for smoothing stepups + + qboolean paused; // send over by server + qboolean onground; + qboolean inwater; + + int intermission; // don't change view angle, full screen, etc + int completed_time; // latched at intermission start + + double mtime[2]; // the timestamp of last two messages + double time; // clients view of time, should be between + // servertime and oldservertime to generate + // a lerp point for other data + double oldtime; // previous cl.time, time-oldtime is used + // to decay light values and smooth step ups + + + float last_received_message; // (realtime) for net trouble icon + +// +// information that is static for the entire time connected to a server +// + struct model_s *model_precache[MAX_MODELS]; + struct sfx_s *sound_precache[MAX_SOUNDS]; + + char levelname[40]; // for display on solo scoreboard + int viewentity; // cl_entitites[cl.viewentity] = player + int maxclients; + int gametype; + +// refresh related state + struct model_s *worldmodel; // cl_entitites[0].model + struct efrag_s *free_efrags; + int num_entities; // held in cl_entities array + int num_statics; // held in cl_staticentities array + entity_t viewent; // the gun model + + int cdtrack, looptrack; // cd audio + +// frag scoreboard + scoreboard_t *scores; // [cl.maxclients] + +#ifdef QUAKE2 +// light level at player's position including dlights +// this is sent back to the server each frame +// architectually ugly but it works + int light_level; +#endif +} client_state_t; + + +// +// cvars +// +extern cvar_t cl_name; +extern cvar_t cl_color; + +extern cvar_t cl_upspeed; +extern cvar_t cl_forwardspeed; +extern cvar_t cl_backspeed; +extern cvar_t cl_sidespeed; + +extern cvar_t cl_movespeedkey; + +extern cvar_t cl_yawspeed; +extern cvar_t cl_pitchspeed; + +extern cvar_t cl_anglespeedkey; + +extern cvar_t cl_autofire; + +extern cvar_t cl_shownet; +extern cvar_t cl_nolerp; + +extern cvar_t cl_pitchdriftspeed; +extern cvar_t lookspring; +extern cvar_t lookstrafe; +extern cvar_t sensitivity; + +extern cvar_t m_pitch; +extern cvar_t m_yaw; +extern cvar_t m_forward; +extern cvar_t m_side; + + +#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc +#define MAX_STATIC_ENTITIES 128 // torches, etc + +extern client_state_t cl; + +// FIXME, allocate dynamically +extern efrag_t cl_efrags[MAX_EFRAGS]; +extern entity_t cl_entities[MAX_EDICTS]; +extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; +extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; +extern dlight_t cl_dlights[MAX_DLIGHTS]; +extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; +extern beam_t cl_beams[MAX_BEAMS]; + +//============================================================================= + +// +// cl_main +// +dlight_t *CL_AllocDlight (int key); +void CL_DecayLights (void); + +void CL_Init (void); + +void CL_EstablishConnection (char *host); +void CL_Signon1 (void); +void CL_Signon2 (void); +void CL_Signon3 (void); +void CL_Signon4 (void); + +void CL_Disconnect (void); +void CL_Disconnect_f (void); +void CL_NextDemo (void); + +#define MAX_VISEDICTS 256 +extern int cl_numvisedicts; +extern entity_t *cl_visedicts[MAX_VISEDICTS]; + +// +// cl_input +// +typedef struct +{ + int down[2]; // key nums holding it down + int state; // low bit is down state +} kbutton_t; + +extern kbutton_t in_mlook, in_klook; +extern kbutton_t in_strafe; +extern kbutton_t in_speed; + +void CL_InitInput (void); +void CL_SendCmd (void); +void CL_SendMove (usercmd_t *cmd); + +void CL_ParseTEnt (void); +void CL_UpdateTEnts (void); + +void CL_ClearState (void); + + +int CL_ReadFromServer (void); +void CL_WriteToServer (usercmd_t *cmd); +void CL_BaseMove (usercmd_t *cmd); + + +float CL_KeyState (kbutton_t *key); +char *Key_KeynumToString (int keynum); + +// +// cl_demo.c +// +void CL_StopPlayback (void); +int CL_GetMessage (void); + +void CL_Stop_f (void); +void CL_Record_f (void); +void CL_PlayDemo_f (void); +void CL_TimeDemo_f (void); + +// +// cl_parse.c +// +void CL_ParseServerMessage (void); +void CL_NewTranslation (int slot); + +// +// view +// +void V_StartPitchDrift (void); +void V_StopPitchDrift (void); + +void V_RenderView (void); +void V_UpdatePalette (void); +void V_Register (void); +void V_ParseDamage (void); +void V_SetContentsColor (int contents); + + +// +// cl_tent +// +void CL_InitTEnts (void); +void CL_SignonReply (void); diff --git a/WinQuake/cmd.c b/WinQuake/cmd.c index 0778c5e..db48924 100644 --- a/WinQuake/cmd.c +++ b/WinQuake/cmd.c @@ -1,705 +1,705 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cmd.c -- Quake script command processing module - -#include "quakedef.h" - -void Cmd_ForwardToServer (void); - -#define MAX_ALIAS_NAME 32 - -typedef struct cmdalias_s -{ - struct cmdalias_s *next; - char name[MAX_ALIAS_NAME]; - char *value; -} cmdalias_t; - -cmdalias_t *cmd_alias; - -int trashtest; -int *trashspot; - -qboolean cmd_wait; - -//============================================================================= - -/* -============ -Cmd_Wait_f - -Causes execution of the remainder of the command buffer to be delayed until -next frame. This allows commands like: -bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" -============ -*/ -void Cmd_Wait_f (void) -{ - cmd_wait = true; -} - -/* -============================================================================= - - COMMAND BUFFER - -============================================================================= -*/ - -sizebuf_t cmd_text; - -/* -============ -Cbuf_Init -============ -*/ -void Cbuf_Init (void) -{ - SZ_Alloc (&cmd_text, 8192); // space for commands and script files -} - - -/* -============ -Cbuf_AddText - -Adds command text at the end of the buffer -============ -*/ -void Cbuf_AddText (char *text) -{ - int l; - - l = Q_strlen (text); - - if (cmd_text.cursize + l >= cmd_text.maxsize) - { - Con_Printf ("Cbuf_AddText: overflow\n"); - return; - } - - SZ_Write (&cmd_text, text, Q_strlen (text)); -} - - -/* -============ -Cbuf_InsertText - -Adds command text immediately after the current command -Adds a \n to the text -FIXME: actually change the command buffer to do less copying -============ -*/ -void Cbuf_InsertText (char *text) -{ - char *temp; - int templen; - -// copy off any commands still remaining in the exec buffer - templen = cmd_text.cursize; - if (templen) - { - temp = Z_Malloc (templen); - Q_memcpy (temp, cmd_text.data, templen); - SZ_Clear (&cmd_text); - } - else - temp = NULL; // shut up compiler - -// add the entire text of the file - Cbuf_AddText (text); - -// add the copied off data - if (templen) - { - SZ_Write (&cmd_text, temp, templen); - Z_Free (temp); - } -} - -/* -============ -Cbuf_Execute -============ -*/ -void Cbuf_Execute (void) -{ - int i; - char *text; - char line[1024]; - int quotes; - - while (cmd_text.cursize) - { -// find a \n or ; line break - text = (char *)cmd_text.data; - - quotes = 0; - for (i=0 ; i< cmd_text.cursize ; i++) - { - if (text[i] == '"') - quotes++; - if ( !(quotes&1) && text[i] == ';') - break; // don't break if inside a quoted string - if (text[i] == '\n') - break; - } - - - memcpy (line, text, i); - line[i] = 0; - -// delete the text from the command buffer and move remaining commands down -// this is necessary because commands (exec, alias) can insert data at the -// beginning of the text buffer - - if (i == cmd_text.cursize) - cmd_text.cursize = 0; - else - { - i++; - cmd_text.cursize -= i; - Q_memcpy (text, text+i, cmd_text.cursize); - } - -// execute the command line - Cmd_ExecuteString (line, src_command); - - if (cmd_wait) - { // skip out while text still remains in buffer, leaving it - // for next frame - cmd_wait = false; - break; - } - } -} - -/* -============================================================================== - - SCRIPT COMMANDS - -============================================================================== -*/ - -/* -=============== -Cmd_StuffCmds_f - -Adds command line parameters as script statements -Commands lead with a +, and continue until a - or another + -quake +prog jctest.qp +cmd amlev1 -quake -nosound +cmd amlev1 -=============== -*/ -void Cmd_StuffCmds_f (void) -{ - int i, j; - int s; - char *text, *build, c; - - if (Cmd_Argc () != 1) - { - Con_Printf ("stuffcmds : execute command line parameters\n"); - return; - } - -// build the combined string to parse from - s = 0; - for (i=1 ; i : execute a script file\n"); - return; - } - - mark = Hunk_LowMark (); - f = (char *)COM_LoadHunkFile (Cmd_Argv(1)); - if (!f) - { - Con_Printf ("couldn't exec %s\n",Cmd_Argv(1)); - return; - } - Con_Printf ("execing %s\n",Cmd_Argv(1)); - - Cbuf_InsertText (f); - Hunk_FreeToLowMark (mark); -} - - -/* -=============== -Cmd_Echo_f - -Just prints the rest of the line to the console -=============== -*/ -void Cmd_Echo_f (void) -{ - int i; - - for (i=1 ; inext) - Con_Printf ("%s : %s\n", a->name, a->value); - return; - } - - s = Cmd_Argv(1); - if (strlen(s) >= MAX_ALIAS_NAME) - { - Con_Printf ("Alias name is too long\n"); - return; - } - - // if the alias allready exists, reuse it - for (a = cmd_alias ; a ; a=a->next) - { - if (!strcmp(s, a->name)) - { - Z_Free (a->value); - break; - } - } - - if (!a) - { - a = Z_Malloc (sizeof(cmdalias_t)); - a->next = cmd_alias; - cmd_alias = a; - } - strcpy (a->name, s); - -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - c = Cmd_Argc(); - for (i=2 ; i< c ; i++) - { - strcat (cmd, Cmd_Argv(i)); - if (i != c) - strcat (cmd, " "); - } - strcat (cmd, "\n"); - - a->value = CopyString (cmd); -} - -/* -============================================================================= - - COMMAND EXECUTION - -============================================================================= -*/ - -typedef struct cmd_function_s -{ - struct cmd_function_s *next; - char *name; - xcommand_t function; -} cmd_function_t; - - -#define MAX_ARGS 80 - -static int cmd_argc; -static char *cmd_argv[MAX_ARGS]; -static char *cmd_null_string = ""; -static char *cmd_args = NULL; - -cmd_source_t cmd_source; - - -static cmd_function_t *cmd_functions; // possible commands to execute - -/* -============ -Cmd_Init -============ -*/ -void Cmd_Init (void) -{ -// -// register our commands -// - Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f); - Cmd_AddCommand ("exec",Cmd_Exec_f); - Cmd_AddCommand ("echo",Cmd_Echo_f); - Cmd_AddCommand ("alias",Cmd_Alias_f); - Cmd_AddCommand ("cmd", Cmd_ForwardToServer); - Cmd_AddCommand ("wait", Cmd_Wait_f); -} - -/* -============ -Cmd_Argc -============ -*/ -int Cmd_Argc (void) -{ - return cmd_argc; -} - -/* -============ -Cmd_Argv -============ -*/ -char *Cmd_Argv (int arg) -{ - if ( (unsigned)arg >= cmd_argc ) - return cmd_null_string; - return cmd_argv[arg]; -} - -/* -============ -Cmd_Args -============ -*/ -char *Cmd_Args (void) -{ - return cmd_args; -} - - -/* -============ -Cmd_TokenizeString - -Parses the given string into command line tokens. -============ -*/ -void Cmd_TokenizeString (char *text) -{ - int i; - -// clear the args from the last string - for (i=0 ; inext) - { - if (!Q_strcmp (cmd_name, cmd->name)) - { - Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); - return; - } - } - - cmd = Hunk_Alloc (sizeof(cmd_function_t)); - cmd->name = cmd_name; - cmd->function = function; - cmd->next = cmd_functions; - cmd_functions = cmd; -} - -/* -============ -Cmd_Exists -============ -*/ -qboolean Cmd_Exists (char *cmd_name) -{ - cmd_function_t *cmd; - - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - { - if (!Q_strcmp (cmd_name,cmd->name)) - return true; - } - - return false; -} - - - -/* -============ -Cmd_CompleteCommand -============ -*/ -char *Cmd_CompleteCommand (char *partial) -{ - cmd_function_t *cmd; - int len; - - len = Q_strlen(partial); - - if (!len) - return NULL; - -// check functions - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - if (!Q_strncmp (partial,cmd->name, len)) - return cmd->name; - - return NULL; -} - -/* -============ -Cmd_ExecuteString - -A complete command line has been parsed, so try to execute it -FIXME: lookupnoadd the token to speed search? -============ -*/ -void Cmd_ExecuteString (char *text, cmd_source_t src) -{ - cmd_function_t *cmd; - cmdalias_t *a; - - cmd_source = src; - Cmd_TokenizeString (text); - -// execute the command line - if (!Cmd_Argc()) - return; // no tokens - -// check functions - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - { - if (!Q_strcasecmp (cmd_argv[0],cmd->name)) - { - cmd->function (); - return; - } - } - -// check alias - for (a=cmd_alias ; a ; a=a->next) - { - if (!Q_strcasecmp (cmd_argv[0], a->name)) - { - Cbuf_InsertText (a->value); - return; - } - } - -// check cvars - if (!Cvar_Command ()) - Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); - -} - - -/* -=================== -Cmd_ForwardToServer - -Sends the entire command line over to the server -=================== -*/ -void Cmd_ForwardToServer (void) -{ - if (cls.state != ca_connected) - { - Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); - return; - } - - if (cls.demoplayback) - return; // not really connected - - MSG_WriteByte (&cls.message, clc_stringcmd); - if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0) - { - SZ_Print (&cls.message, Cmd_Argv(0)); - SZ_Print (&cls.message, " "); - } - if (Cmd_Argc() > 1) - SZ_Print (&cls.message, Cmd_Args()); - else - SZ_Print (&cls.message, "\n"); -} - - -/* -================ -Cmd_CheckParm - -Returns the position (1 to argc-1) in the command's argument list -where the given parameter apears, or 0 if not present -================ -*/ - -int Cmd_CheckParm (char *parm) -{ - int i; - - if (!parm) - Sys_Error ("Cmd_CheckParm: NULL"); - - for (i = 1; i < Cmd_Argc (); i++) - if (! Q_strcasecmp (parm, Cmd_Argv (i))) - return i; - - return 0; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cmd.c -- Quake script command processing module + +#include "quakedef.h" + +void Cmd_ForwardToServer (void); + +#define MAX_ALIAS_NAME 32 + +typedef struct cmdalias_s +{ + struct cmdalias_s *next; + char name[MAX_ALIAS_NAME]; + char *value; +} cmdalias_t; + +cmdalias_t *cmd_alias; + +int trashtest; +int *trashspot; + +qboolean cmd_wait; + +//============================================================================= + +/* +============ +Cmd_Wait_f + +Causes execution of the remainder of the command buffer to be delayed until +next frame. This allows commands like: +bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" +============ +*/ +void Cmd_Wait_f (void) +{ + cmd_wait = true; +} + +/* +============================================================================= + + COMMAND BUFFER + +============================================================================= +*/ + +sizebuf_t cmd_text; + +/* +============ +Cbuf_Init +============ +*/ +void Cbuf_Init (void) +{ + SZ_Alloc (&cmd_text, 8192); // space for commands and script files +} + + +/* +============ +Cbuf_AddText + +Adds command text at the end of the buffer +============ +*/ +void Cbuf_AddText (char *text) +{ + int l; + + l = Q_strlen (text); + + if (cmd_text.cursize + l >= cmd_text.maxsize) + { + Con_Printf ("Cbuf_AddText: overflow\n"); + return; + } + + SZ_Write (&cmd_text, text, Q_strlen (text)); +} + + +/* +============ +Cbuf_InsertText + +Adds command text immediately after the current command +Adds a \n to the text +FIXME: actually change the command buffer to do less copying +============ +*/ +void Cbuf_InsertText (char *text) +{ + char *temp; + int templen; + +// copy off any commands still remaining in the exec buffer + templen = cmd_text.cursize; + if (templen) + { + temp = Z_Malloc (templen); + Q_memcpy (temp, cmd_text.data, templen); + SZ_Clear (&cmd_text); + } + else + temp = NULL; // shut up compiler + +// add the entire text of the file + Cbuf_AddText (text); + +// add the copied off data + if (templen) + { + SZ_Write (&cmd_text, temp, templen); + Z_Free (temp); + } +} + +/* +============ +Cbuf_Execute +============ +*/ +void Cbuf_Execute (void) +{ + int i; + char *text; + char line[1024]; + int quotes; + + while (cmd_text.cursize) + { +// find a \n or ; line break + text = (char *)cmd_text.data; + + quotes = 0; + for (i=0 ; i< cmd_text.cursize ; i++) + { + if (text[i] == '"') + quotes++; + if ( !(quotes&1) && text[i] == ';') + break; // don't break if inside a quoted string + if (text[i] == '\n') + break; + } + + + memcpy (line, text, i); + line[i] = 0; + +// delete the text from the command buffer and move remaining commands down +// this is necessary because commands (exec, alias) can insert data at the +// beginning of the text buffer + + if (i == cmd_text.cursize) + cmd_text.cursize = 0; + else + { + i++; + cmd_text.cursize -= i; + Q_memcpy (text, text+i, cmd_text.cursize); + } + +// execute the command line + Cmd_ExecuteString (line, src_command); + + if (cmd_wait) + { // skip out while text still remains in buffer, leaving it + // for next frame + cmd_wait = false; + break; + } + } +} + +/* +============================================================================== + + SCRIPT COMMANDS + +============================================================================== +*/ + +/* +=============== +Cmd_StuffCmds_f + +Adds command line parameters as script statements +Commands lead with a +, and continue until a - or another + +quake +prog jctest.qp +cmd amlev1 +quake -nosound +cmd amlev1 +=============== +*/ +void Cmd_StuffCmds_f (void) +{ + int i, j; + int s; + char *text, *build, c; + + if (Cmd_Argc () != 1) + { + Con_Printf ("stuffcmds : execute command line parameters\n"); + return; + } + +// build the combined string to parse from + s = 0; + for (i=1 ; i : execute a script file\n"); + return; + } + + mark = Hunk_LowMark (); + f = (char *)COM_LoadHunkFile (Cmd_Argv(1)); + if (!f) + { + Con_Printf ("couldn't exec %s\n",Cmd_Argv(1)); + return; + } + Con_Printf ("execing %s\n",Cmd_Argv(1)); + + Cbuf_InsertText (f); + Hunk_FreeToLowMark (mark); +} + + +/* +=============== +Cmd_Echo_f + +Just prints the rest of the line to the console +=============== +*/ +void Cmd_Echo_f (void) +{ + int i; + + for (i=1 ; inext) + Con_Printf ("%s : %s\n", a->name, a->value); + return; + } + + s = Cmd_Argv(1); + if (strlen(s) >= MAX_ALIAS_NAME) + { + Con_Printf ("Alias name is too long\n"); + return; + } + + // if the alias allready exists, reuse it + for (a = cmd_alias ; a ; a=a->next) + { + if (!strcmp(s, a->name)) + { + Z_Free (a->value); + break; + } + } + + if (!a) + { + a = Z_Malloc (sizeof(cmdalias_t)); + a->next = cmd_alias; + cmd_alias = a; + } + strcpy (a->name, s); + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + c = Cmd_Argc(); + for (i=2 ; i< c ; i++) + { + strcat (cmd, Cmd_Argv(i)); + if (i != c) + strcat (cmd, " "); + } + strcat (cmd, "\n"); + + a->value = CopyString (cmd); +} + +/* +============================================================================= + + COMMAND EXECUTION + +============================================================================= +*/ + +typedef struct cmd_function_s +{ + struct cmd_function_s *next; + char *name; + xcommand_t function; +} cmd_function_t; + + +#define MAX_ARGS 80 + +static int cmd_argc; +static char *cmd_argv[MAX_ARGS]; +static char *cmd_null_string = ""; +static char *cmd_args = NULL; + +cmd_source_t cmd_source; + + +static cmd_function_t *cmd_functions; // possible commands to execute + +/* +============ +Cmd_Init +============ +*/ +void Cmd_Init (void) +{ +// +// register our commands +// + Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f); + Cmd_AddCommand ("exec",Cmd_Exec_f); + Cmd_AddCommand ("echo",Cmd_Echo_f); + Cmd_AddCommand ("alias",Cmd_Alias_f); + Cmd_AddCommand ("cmd", Cmd_ForwardToServer); + Cmd_AddCommand ("wait", Cmd_Wait_f); +} + +/* +============ +Cmd_Argc +============ +*/ +int Cmd_Argc (void) +{ + return cmd_argc; +} + +/* +============ +Cmd_Argv +============ +*/ +char *Cmd_Argv (int arg) +{ + if ( (unsigned)arg >= cmd_argc ) + return cmd_null_string; + return cmd_argv[arg]; +} + +/* +============ +Cmd_Args +============ +*/ +char *Cmd_Args (void) +{ + return cmd_args; +} + + +/* +============ +Cmd_TokenizeString + +Parses the given string into command line tokens. +============ +*/ +void Cmd_TokenizeString (char *text) +{ + int i; + +// clear the args from the last string + for (i=0 ; inext) + { + if (!Q_strcmp (cmd_name, cmd->name)) + { + Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); + return; + } + } + + cmd = Hunk_Alloc (sizeof(cmd_function_t)); + cmd->name = cmd_name; + cmd->function = function; + cmd->next = cmd_functions; + cmd_functions = cmd; +} + +/* +============ +Cmd_Exists +============ +*/ +qboolean Cmd_Exists (char *cmd_name) +{ + cmd_function_t *cmd; + + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + { + if (!Q_strcmp (cmd_name,cmd->name)) + return true; + } + + return false; +} + + + +/* +============ +Cmd_CompleteCommand +============ +*/ +char *Cmd_CompleteCommand (char *partial) +{ + cmd_function_t *cmd; + int len; + + len = Q_strlen(partial); + + if (!len) + return NULL; + +// check functions + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + if (!Q_strncmp (partial,cmd->name, len)) + return cmd->name; + + return NULL; +} + +/* +============ +Cmd_ExecuteString + +A complete command line has been parsed, so try to execute it +FIXME: lookupnoadd the token to speed search? +============ +*/ +void Cmd_ExecuteString (char *text, cmd_source_t src) +{ + cmd_function_t *cmd; + cmdalias_t *a; + + cmd_source = src; + Cmd_TokenizeString (text); + +// execute the command line + if (!Cmd_Argc()) + return; // no tokens + +// check functions + for (cmd=cmd_functions ; cmd ; cmd=cmd->next) + { + if (!Q_strcasecmp (cmd_argv[0],cmd->name)) + { + cmd->function (); + return; + } + } + +// check alias + for (a=cmd_alias ; a ; a=a->next) + { + if (!Q_strcasecmp (cmd_argv[0], a->name)) + { + Cbuf_InsertText (a->value); + return; + } + } + +// check cvars + if (!Cvar_Command ()) + Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); + +} + + +/* +=================== +Cmd_ForwardToServer + +Sends the entire command line over to the server +=================== +*/ +void Cmd_ForwardToServer (void) +{ + if (cls.state != ca_connected) + { + Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0)); + return; + } + + if (cls.demoplayback) + return; // not really connected + + MSG_WriteByte (&cls.message, clc_stringcmd); + if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0) + { + SZ_Print (&cls.message, Cmd_Argv(0)); + SZ_Print (&cls.message, " "); + } + if (Cmd_Argc() > 1) + SZ_Print (&cls.message, Cmd_Args()); + else + SZ_Print (&cls.message, "\n"); +} + + +/* +================ +Cmd_CheckParm + +Returns the position (1 to argc-1) in the command's argument list +where the given parameter apears, or 0 if not present +================ +*/ + +int Cmd_CheckParm (char *parm) +{ + int i; + + if (!parm) + Sys_Error ("Cmd_CheckParm: NULL"); + + for (i = 1; i < Cmd_Argc (); i++) + if (! Q_strcasecmp (parm, Cmd_Argv (i))) + return i; + + return 0; +} diff --git a/WinQuake/cmd.h b/WinQuake/cmd.h index f9eab24..b2e9993 100644 --- a/WinQuake/cmd.h +++ b/WinQuake/cmd.h @@ -1,121 +1,121 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// cmd.h -- Command buffer and command execution - -//=========================================================================== - -/* - -Any number of commands can be added in a frame, from several different sources. -Most commands come from either keybindings or console line input, but remote -servers can also send across commands and entire text files can be execed. - -The + command line options are also added to the command buffer. - -The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute (); - -*/ - - -void Cbuf_Init (void); -// allocates an initial text buffer that will grow as needed - -void Cbuf_AddText (char *text); -// as new commands are generated from the console or keybindings, -// the text is added to the end of the command buffer. - -void Cbuf_InsertText (char *text); -// when a command wants to issue other commands immediately, the text is -// inserted at the beginning of the buffer, before any remaining unexecuted -// commands. - -void Cbuf_Execute (void); -// Pulls off \n terminated lines of text from the command buffer and sends -// them through Cmd_ExecuteString. Stops when the buffer is empty. -// Normally called once per frame, but may be explicitly invoked. -// Do not call inside a command function! - -//=========================================================================== - -/* - -Command execution takes a null terminated string, breaks it into tokens, -then searches for a command or variable that matches the first token. - -Commands can come from three sources, but the handler functions may choose -to dissallow the action or forward it to a remote server if the source is -not apropriate. - -*/ - -typedef void (*xcommand_t) (void); - -typedef enum -{ - src_client, // came in over a net connection as a clc_stringcmd - // host_client will be valid during this state. - src_command // from the command buffer -} cmd_source_t; - -extern cmd_source_t cmd_source; - -void Cmd_Init (void); - -void Cmd_AddCommand (char *cmd_name, xcommand_t function); -// called by the init functions of other parts of the program to -// register commands and functions to call for them. -// The cmd_name is referenced later, so it should not be in temp memory - -qboolean Cmd_Exists (char *cmd_name); -// used by the cvar code to check for cvar / command name overlap - -char *Cmd_CompleteCommand (char *partial); -// attempts to match a partial command for automatic command line completion -// returns NULL if nothing fits - -int Cmd_Argc (void); -char *Cmd_Argv (int arg); -char *Cmd_Args (void); -// The functions that execute commands get their parameters with these -// functions. Cmd_Argv () will return an empty string, not a NULL -// if arg > argc, so string operations are allways safe. - -int Cmd_CheckParm (char *parm); -// Returns the position (1 to argc-1) in the command's argument list -// where the given parameter apears, or 0 if not present - -void Cmd_TokenizeString (char *text); -// Takes a null terminated string. Does not need to be /n terminated. -// breaks the string up into arg tokens. - -void Cmd_ExecuteString (char *text, cmd_source_t src); -// Parses a single line of text into arguments and tries to execute it. -// The text can come from the command buffer, a remote client, or stdin. - -void Cmd_ForwardToServer (void); -// adds the current command line as a clc_stringcmd to the client message. -// things like godmode, noclip, etc, are commands directed to the server, -// so when they are typed in at the console, they will need to be forwarded. - -void Cmd_Print (char *text); -// used by command functions to send output to either the graphics console or -// passed as a print message to the client - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// cmd.h -- Command buffer and command execution + +//=========================================================================== + +/* + +Any number of commands can be added in a frame, from several different sources. +Most commands come from either keybindings or console line input, but remote +servers can also send across commands and entire text files can be execed. + +The + command line options are also added to the command buffer. + +The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute (); + +*/ + + +void Cbuf_Init (void); +// allocates an initial text buffer that will grow as needed + +void Cbuf_AddText (char *text); +// as new commands are generated from the console or keybindings, +// the text is added to the end of the command buffer. + +void Cbuf_InsertText (char *text); +// when a command wants to issue other commands immediately, the text is +// inserted at the beginning of the buffer, before any remaining unexecuted +// commands. + +void Cbuf_Execute (void); +// Pulls off \n terminated lines of text from the command buffer and sends +// them through Cmd_ExecuteString. Stops when the buffer is empty. +// Normally called once per frame, but may be explicitly invoked. +// Do not call inside a command function! + +//=========================================================================== + +/* + +Command execution takes a null terminated string, breaks it into tokens, +then searches for a command or variable that matches the first token. + +Commands can come from three sources, but the handler functions may choose +to dissallow the action or forward it to a remote server if the source is +not apropriate. + +*/ + +typedef void (*xcommand_t) (void); + +typedef enum +{ + src_client, // came in over a net connection as a clc_stringcmd + // host_client will be valid during this state. + src_command // from the command buffer +} cmd_source_t; + +extern cmd_source_t cmd_source; + +void Cmd_Init (void); + +void Cmd_AddCommand (char *cmd_name, xcommand_t function); +// called by the init functions of other parts of the program to +// register commands and functions to call for them. +// The cmd_name is referenced later, so it should not be in temp memory + +qboolean Cmd_Exists (char *cmd_name); +// used by the cvar code to check for cvar / command name overlap + +char *Cmd_CompleteCommand (char *partial); +// attempts to match a partial command for automatic command line completion +// returns NULL if nothing fits + +int Cmd_Argc (void); +char *Cmd_Argv (int arg); +char *Cmd_Args (void); +// The functions that execute commands get their parameters with these +// functions. Cmd_Argv () will return an empty string, not a NULL +// if arg > argc, so string operations are allways safe. + +int Cmd_CheckParm (char *parm); +// Returns the position (1 to argc-1) in the command's argument list +// where the given parameter apears, or 0 if not present + +void Cmd_TokenizeString (char *text); +// Takes a null terminated string. Does not need to be /n terminated. +// breaks the string up into arg tokens. + +void Cmd_ExecuteString (char *text, cmd_source_t src); +// Parses a single line of text into arguments and tries to execute it. +// The text can come from the command buffer, a remote client, or stdin. + +void Cmd_ForwardToServer (void); +// adds the current command line as a clc_stringcmd to the client message. +// things like godmode, noclip, etc, are commands directed to the server, +// so when they are typed in at the console, they will need to be forwarded. + +void Cmd_Print (char *text); +// used by command functions to send output to either the graphics console or +// passed as a print message to the client + diff --git a/WinQuake/common.c b/WinQuake/common.c index e07e6ce..a6f6bd9 100644 --- a/WinQuake/common.c +++ b/WinQuake/common.c @@ -1,1827 +1,1827 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// common.c -- misc functions used in client and server - -#include "quakedef.h" - -#define NUM_SAFE_ARGVS 7 - -static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; -static char *argvdummy = " "; - -static char *safeargvs[NUM_SAFE_ARGVS] = - {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"}; - -cvar_t registered = {"registered","0"}; -cvar_t cmdline = {"cmdline","0", false, true}; - -qboolean com_modified; // set true if using non-id files - -qboolean proghack; - -int static_registered = 1; // only for startup check, then set - -qboolean msg_suppress_1 = 0; - -void COM_InitFilesystem (void); - -// if a packfile directory differs from this, it is assumed to be hacked -#define PAK0_COUNT 339 -#define PAK0_CRC 32981 - -char com_token[1024]; -int com_argc; -char **com_argv; - -#define CMDLINE_LENGTH 256 -char com_cmdline[CMDLINE_LENGTH]; - -qboolean standard_quake = true, rogue, hipnotic; - -// this graphic needs to be in the pak file to use registered features -unsigned short pop[] = -{ - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000 -,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000 -,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600 -,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563 -,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564 -,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564 -,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563 -,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500 -,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200 -,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000 -,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000 -}; - -/* - - -All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources. - -The "base directory" is the path to the directory holding the quake.exe and all game directories. The sys_* files pass this to host_init in quakeparms_t->basedir. This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory. The base directory is -only used during filesystem initialization. - -The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to. This can be overridden with the "-game" command line parameter. The game directory can never be changed while quake is executing. This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't. - -The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines. If there is a cache directory -specified, when a file is found by the normal search path, it will be mirrored -into the cache directory, then opened there. - - - -FIXME: -The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line. - -*/ - -//============================================================================ - - -// ClearLink is used for new headnodes -void ClearLink (link_t *l) -{ - l->prev = l->next = l; -} - -void RemoveLink (link_t *l) -{ - l->next->prev = l->prev; - l->prev->next = l->next; -} - -void InsertLinkBefore (link_t *l, link_t *before) -{ - l->next = before; - l->prev = before->prev; - l->prev->next = l; - l->next->prev = l; -} -void InsertLinkAfter (link_t *l, link_t *after) -{ - l->next = after->next; - l->prev = after; - l->prev->next = l; - l->next->prev = l; -} - -/* -============================================================================ - - LIBRARY REPLACEMENT FUNCTIONS - -============================================================================ -*/ - -void Q_memset (void *dest, int fill, int count) -{ - int i; - - if ( (((long)dest | count) & 3) == 0) - { - count >>= 2; - fill = fill | (fill<<8) | (fill<<16) | (fill<<24); - for (i=0 ; i>=2; - for (i=0 ; i= 'a' && c1 <= 'z') - c1 -= ('a' - 'A'); - if (c2 >= 'a' && c2 <= 'z') - c2 -= ('a' - 'A'); - if (c1 != c2) - return -1; // strings not equal - } - if (!c1) - return 0; // strings are equal -// s1++; -// s2++; - } - - return -1; -} - -int Q_strcasecmp (char *s1, char *s2) -{ - return Q_strncasecmp (s1, s2, 99999); -} - -int Q_atoi (char *str) -{ - int val; - int sign; - int c; - - if (*str == '-') - { - sign = -1; - str++; - } - else - sign = 1; - - val = 0; - -// -// check for hex -// - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) - { - str += 2; - while (1) - { - c = *str++; - if (c >= '0' && c <= '9') - val = (val<<4) + c - '0'; - else if (c >= 'a' && c <= 'f') - val = (val<<4) + c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = (val<<4) + c - 'A' + 10; - else - return val*sign; - } - } - -// -// check for character -// - if (str[0] == '\'') - { - return sign * str[1]; - } - -// -// assume decimal -// - while (1) - { - c = *str++; - if (c <'0' || c > '9') - return val*sign; - val = val*10 + c - '0'; - } - - return 0; -} - - -float Q_atof (char *str) -{ - double val; - int sign; - int c; - int decimal, total; - - if (*str == '-') - { - sign = -1; - str++; - } - else - sign = 1; - - val = 0; - -// -// check for hex -// - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) - { - str += 2; - while (1) - { - c = *str++; - if (c >= '0' && c <= '9') - val = (val*16) + c - '0'; - else if (c >= 'a' && c <= 'f') - val = (val*16) + c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = (val*16) + c - 'A' + 10; - else - return val*sign; - } - } - -// -// check for character -// - if (str[0] == '\'') - { - return sign * str[1]; - } - -// -// assume decimal -// - decimal = -1; - total = 0; - while (1) - { - c = *str++; - if (c == '.') - { - decimal = total; - continue; - } - if (c <'0' || c > '9') - break; - val = val*10 + c - '0'; - total++; - } - - if (decimal == -1) - return val*sign; - while (total > decimal) - { - val /= 10; - total--; - } - - return val*sign; -} - -/* -============================================================================ - - BYTE ORDER FUNCTIONS - -============================================================================ -*/ - -qboolean bigendien; - -short (*BigShort) (short l); -short (*LittleShort) (short l); -int (*BigLong) (int l); -int (*LittleLong) (int l); -float (*BigFloat) (float l); -float (*LittleFloat) (float l); - -short ShortSwap (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short ShortNoSwap (short l) -{ - return l; -} - -int LongSwap (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int LongNoSwap (int l) -{ - return l; -} - -float FloatSwap (float f) -{ - union - { - float f; - byte b[4]; - } dat1, dat2; - - - dat1.f = f; - dat2.b[0] = dat1.b[3]; - dat2.b[1] = dat1.b[2]; - dat2.b[2] = dat1.b[1]; - dat2.b[3] = dat1.b[0]; - return dat2.f; -} - -float FloatNoSwap (float f) -{ - return f; -} - -/* -============================================================================== - - MESSAGE IO FUNCTIONS - -Handles byte ordering and avoids alignment errors -============================================================================== -*/ - -// -// writing functions -// - -void MSG_WriteChar (sizebuf_t *sb, int c) -{ - byte *buf; - -#ifdef PARANOID - if (c < -128 || c > 127) - Sys_Error ("MSG_WriteChar: range error"); -#endif - - buf = SZ_GetSpace (sb, 1); - buf[0] = c; -} - -void MSG_WriteByte (sizebuf_t *sb, int c) -{ - byte *buf; - -#ifdef PARANOID - if (c < 0 || c > 255) - Sys_Error ("MSG_WriteByte: range error"); -#endif - - buf = SZ_GetSpace (sb, 1); - buf[0] = c; -} - -void MSG_WriteShort (sizebuf_t *sb, int c) -{ - byte *buf; - -#ifdef PARANOID - if (c < ((short)0x8000) || c > (short)0x7fff) - Sys_Error ("MSG_WriteShort: range error"); -#endif - - buf = SZ_GetSpace (sb, 2); - buf[0] = c&0xff; - buf[1] = c>>8; -} - -void MSG_WriteLong (sizebuf_t *sb, int c) -{ - byte *buf; - - buf = SZ_GetSpace (sb, 4); - buf[0] = c&0xff; - buf[1] = (c>>8)&0xff; - buf[2] = (c>>16)&0xff; - buf[3] = c>>24; -} - -void MSG_WriteFloat (sizebuf_t *sb, float f) -{ - union - { - float f; - int l; - } dat; - - - dat.f = f; - dat.l = LittleLong (dat.l); - - SZ_Write (sb, &dat.l, 4); -} - -void MSG_WriteString (sizebuf_t *sb, char *s) -{ - if (!s) - SZ_Write (sb, "", 1); - else - SZ_Write (sb, s, Q_strlen(s)+1); -} - -void MSG_WriteCoord (sizebuf_t *sb, float f) -{ - MSG_WriteShort (sb, (int)(f*8)); -} - -void MSG_WriteAngle (sizebuf_t *sb, float f) -{ - MSG_WriteByte (sb, ((int)f*256/360) & 255); -} - -// -// reading functions -// -int msg_readcount; -qboolean msg_badread; - -void MSG_BeginReading (void) -{ - msg_readcount = 0; - msg_badread = false; -} - -// returns -1 and sets msg_badread if no more characters are available -int MSG_ReadChar (void) -{ - int c; - - if (msg_readcount+1 > net_message.cursize) - { - msg_badread = true; - return -1; - } - - c = (signed char)net_message.data[msg_readcount]; - msg_readcount++; - - return c; -} - -int MSG_ReadByte (void) -{ - int c; - - if (msg_readcount+1 > net_message.cursize) - { - msg_badread = true; - return -1; - } - - c = (unsigned char)net_message.data[msg_readcount]; - msg_readcount++; - - return c; -} - -int MSG_ReadShort (void) -{ - int c; - - if (msg_readcount+2 > net_message.cursize) - { - msg_badread = true; - return -1; - } - - c = (short)(net_message.data[msg_readcount] - + (net_message.data[msg_readcount+1]<<8)); - - msg_readcount += 2; - - return c; -} - -int MSG_ReadLong (void) -{ - int c; - - if (msg_readcount+4 > net_message.cursize) - { - msg_badread = true; - return -1; - } - - c = net_message.data[msg_readcount] - + (net_message.data[msg_readcount+1]<<8) - + (net_message.data[msg_readcount+2]<<16) - + (net_message.data[msg_readcount+3]<<24); - - msg_readcount += 4; - - return c; -} - -float MSG_ReadFloat (void) -{ - union - { - byte b[4]; - float f; - int l; - } dat; - - dat.b[0] = net_message.data[msg_readcount]; - dat.b[1] = net_message.data[msg_readcount+1]; - dat.b[2] = net_message.data[msg_readcount+2]; - dat.b[3] = net_message.data[msg_readcount+3]; - msg_readcount += 4; - - dat.l = LittleLong (dat.l); - - return dat.f; -} - -char *MSG_ReadString (void) -{ - static char string[2048]; - int l,c; - - l = 0; - do - { - c = MSG_ReadChar (); - if (c == -1 || c == 0) - break; - string[l] = c; - l++; - } while (l < sizeof(string)-1); - - string[l] = 0; - - return string; -} - -float MSG_ReadCoord (void) -{ - return MSG_ReadShort() * (1.0/8); -} - -float MSG_ReadAngle (void) -{ - return MSG_ReadChar() * (360.0/256); -} - - - -//=========================================================================== - -void SZ_Alloc (sizebuf_t *buf, int startsize) -{ - if (startsize < 256) - startsize = 256; - buf->data = Hunk_AllocName (startsize, "sizebuf"); - buf->maxsize = startsize; - buf->cursize = 0; -} - - -void SZ_Free (sizebuf_t *buf) -{ -// Z_Free (buf->data); -// buf->data = NULL; -// buf->maxsize = 0; - buf->cursize = 0; -} - -void SZ_Clear (sizebuf_t *buf) -{ - buf->cursize = 0; -} - -void *SZ_GetSpace (sizebuf_t *buf, int length) -{ - void *data; - - if (buf->cursize + length > buf->maxsize) - { - if (!buf->allowoverflow) - Sys_Error ("SZ_GetSpace: overflow without allowoverflow set"); - - if (length > buf->maxsize) - Sys_Error ("SZ_GetSpace: %i is > full buffer size", length); - - buf->overflowed = true; - Con_Printf ("SZ_GetSpace: overflow"); - SZ_Clear (buf); - } - - data = buf->data + buf->cursize; - buf->cursize += length; - - return data; -} - -void SZ_Write (sizebuf_t *buf, void *data, int length) -{ - Q_memcpy (SZ_GetSpace(buf,length),data,length); -} - -void SZ_Print (sizebuf_t *buf, char *data) -{ - int len; - - len = Q_strlen(data)+1; - -// byte * cast to keep VC++ happy - if (buf->data[buf->cursize-1]) - Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0 - else - Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0 -} - - -//============================================================================ - - -/* -============ -COM_SkipPath -============ -*/ -char *COM_SkipPath (char *pathname) -{ - char *last; - - last = pathname; - while (*pathname) - { - if (*pathname=='/') - last = pathname+1; - pathname++; - } - return last; -} - -/* -============ -COM_StripExtension -============ -*/ -void COM_StripExtension (char *in, char *out) -{ - while (*in && *in != '.') - *out++ = *in++; - *out = 0; -} - -/* -============ -COM_FileExtension -============ -*/ -char *COM_FileExtension (char *in) -{ - static char exten[8]; - int i; - - while (*in && *in != '.') - in++; - if (!*in) - return ""; - in++; - for (i=0 ; i<7 && *in ; i++,in++) - exten[i] = *in; - exten[i] = 0; - return exten; -} - -/* -============ -COM_FileBase -============ -*/ -void COM_FileBase (char *in, char *out) -{ - char *s, *s2; - - s = in + strlen(in) - 1; - - while (s != in && *s != '.') - s--; - - for (s2 = s ; *s2 && *s2 != '/' ; s2--) - ; - - if (s-s2 < 2) - strcpy (out,"?model?"); - else - { - s--; - strncpy (out,s2+1, s-s2); - out[s-s2] = 0; - } -} - - -/* -================== -COM_DefaultExtension -================== -*/ -void COM_DefaultExtension (char *path, char *extension) -{ - char *src; -// -// if path doesn't have a .EXT, append extension -// (extension should include the .) -// - src = path + strlen(path) - 1; - - while (*src != '/' && src != path) - { - if (*src == '.') - return; // it has an extension - src--; - } - - strcat (path, extension); -} - - -/* -============== -COM_Parse - -Parse a token out of a string -============== -*/ -char *COM_Parse (char *data) -{ - int c; - int len; - - len = 0; - com_token[0] = 0; - - if (!data) - return NULL; - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - return NULL; // end of file; - data++; - } - -// skip // comments - if (c=='/' && data[1] == '/') - { - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if (c == '\"') - { - data++; - while (1) - { - c = *data++; - if (c=='\"' || !c) - { - com_token[len] = 0; - return data; - } - com_token[len] = c; - len++; - } - } - -// parse single characters - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - { - com_token[len] = c; - len++; - com_token[len] = 0; - return data+1; - } - -// parse a regular word - do - { - com_token[len] = c; - data++; - len++; - c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - break; - } while (c>32); - - com_token[len] = 0; - return data; -} - - -/* -================ -COM_CheckParm - -Returns the position (1 to argc-1) in the program's argument list -where the given parameter apears, or 0 if not present -================ -*/ -int COM_CheckParm (char *parm) -{ - int i; - - for (i=1 ; inext) - { - if (s->pack) - { - Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles); - } - else - Con_Printf ("%s\n", s->filename); - } -} - -/* -============ -COM_WriteFile - -The filename will be prefixed by the current game directory -============ -*/ -void COM_WriteFile (char *filename, void *data, int len) -{ - int handle; - char name[MAX_OSPATH]; - - sprintf (name, "%s/%s", com_gamedir, filename); - - handle = Sys_FileOpenWrite (name); - if (handle == -1) - { - Sys_Printf ("COM_WriteFile: failed on %s\n", name); - return; - } - - Sys_Printf ("COM_WriteFile: %s\n", name); - Sys_FileWrite (handle, data, len); - Sys_FileClose (handle); -} - - -/* -============ -COM_CreatePath - -Only used for CopyFile -============ -*/ -void COM_CreatePath (char *path) -{ - char *ofs; - - for (ofs = path+1 ; *ofs ; ofs++) - { - if (*ofs == '/') - { // create the directory - *ofs = 0; - Sys_mkdir (path); - *ofs = '/'; - } - } -} - - -/* -=========== -COM_CopyFile - -Copies a file over from the net to the local cache, creating any directories -needed. This is for the convenience of developers using ISDN from home. -=========== -*/ -void COM_CopyFile (char *netpath, char *cachepath) -{ - int in, out; - int remaining, count; - char buf[4096]; - - remaining = Sys_FileOpenRead (netpath, &in); - COM_CreatePath (cachepath); // create directories up to the cache file - out = Sys_FileOpenWrite (cachepath); - - while (remaining) - { - if (remaining < sizeof(buf)) - count = remaining; - else - count = sizeof(buf); - Sys_FileRead (in, buf, count); - Sys_FileWrite (out, buf, count); - remaining -= count; - } - - Sys_FileClose (in); - Sys_FileClose (out); -} - -/* -=========== -COM_FindFile - -Finds the file in the search path. -Sets com_filesize and one of handle or file -=========== -*/ -int COM_FindFile (char *filename, int *handle, FILE **file) -{ - searchpath_t *search; - char netpath[MAX_OSPATH]; - char cachepath[MAX_OSPATH]; - pack_t *pak; - int i; - int findtime, cachetime; - - if (file && handle) - Sys_Error ("COM_FindFile: both handle and file set"); - if (!file && !handle) - Sys_Error ("COM_FindFile: neither handle or file set"); - -// -// search through the path, one element at a time -// - search = com_searchpaths; - if (proghack) - { // gross hack to use quake 1 progs with quake 2 maps - if (!strcmp(filename, "progs.dat")) - search = search->next; - } - - for ( ; search ; search = search->next) - { - // is the element a pak file? - if (search->pack) - { - // look through all the pak file elements - pak = search->pack; - for (i=0 ; inumfiles ; i++) - if (!strcmp (pak->files[i].name, filename)) - { // found it! - Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename); - if (handle) - { - *handle = pak->handle; - Sys_FileSeek (pak->handle, pak->files[i].filepos); - } - else - { // open a new file on the pakfile - *file = fopen (pak->filename, "rb"); - if (*file) - fseek (*file, pak->files[i].filepos, SEEK_SET); - } - com_filesize = pak->files[i].filelen; - return com_filesize; - } - } - else - { - // check a file in the directory tree - if (!static_registered) - { // if not a registered version, don't ever go beyond base - if ( strchr (filename, '/') || strchr (filename,'\\')) - continue; - } - - sprintf (netpath, "%s/%s",search->filename, filename); - - findtime = Sys_FileTime (netpath); - if (findtime == -1) - continue; - - // see if the file needs to be updated in the cache - if (!com_cachedir[0]) - strcpy (cachepath, netpath); - else - { -#if defined(_WIN32) - if ((strlen(netpath) < 2) || (netpath[1] != ':')) - sprintf (cachepath,"%s%s", com_cachedir, netpath); - else - sprintf (cachepath,"%s%s", com_cachedir, netpath+2); -#else - sprintf (cachepath,"%s%s", com_cachedir, netpath); -#endif - - cachetime = Sys_FileTime (cachepath); - - if (cachetime < findtime) - COM_CopyFile (netpath, cachepath); - strcpy (netpath, cachepath); - } - - Sys_Printf ("FindFile: %s\n",netpath); - com_filesize = Sys_FileOpenRead (netpath, &i); - if (handle) - *handle = i; - else - { - Sys_FileClose (i); - *file = fopen (netpath, "rb"); - } - return com_filesize; - } - - } - - Sys_Printf ("FindFile: can't find %s\n", filename); - - if (handle) - *handle = -1; - else - *file = NULL; - com_filesize = -1; - return -1; -} - - -/* -=========== -COM_OpenFile - -filename never has a leading slash, but may contain directory walks -returns a handle and a length -it may actually be inside a pak file -=========== -*/ -int COM_OpenFile (char *filename, int *handle) -{ - return COM_FindFile (filename, handle, NULL); -} - -/* -=========== -COM_FOpenFile - -If the requested file is inside a packfile, a new FILE * will be opened -into the file. -=========== -*/ -int COM_FOpenFile (char *filename, FILE **file) -{ - return COM_FindFile (filename, NULL, file); -} - -/* -============ -COM_CloseFile - -If it is a pak file handle, don't really close it -============ -*/ -void COM_CloseFile (int h) -{ - searchpath_t *s; - - for (s = com_searchpaths ; s ; s=s->next) - if (s->pack && s->pack->handle == h) - return; - - Sys_FileClose (h); -} - - -/* -============ -COM_LoadFile - -Filename are reletive to the quake directory. -Allways appends a 0 byte. -============ -*/ -cache_user_t *loadcache; -byte *loadbuf; -int loadsize; -byte *COM_LoadFile (char *path, int usehunk) -{ - int h; - byte *buf; - char base[32]; - int len; - - buf = NULL; // quiet compiler warning - -// look for it in the filesystem or pack files - len = COM_OpenFile (path, &h); - if (h == -1) - return NULL; - -// extract the filename base name for hunk tag - COM_FileBase (path, base); - - if (usehunk == 1) - buf = Hunk_AllocName (len+1, base); - else if (usehunk == 2) - buf = Hunk_TempAlloc (len+1); - else if (usehunk == 0) - buf = Z_Malloc (len+1); - else if (usehunk == 3) - buf = Cache_Alloc (loadcache, len+1, base); - else if (usehunk == 4) - { - if (len+1 > loadsize) - buf = Hunk_TempAlloc (len+1); - else - buf = loadbuf; - } - else - Sys_Error ("COM_LoadFile: bad usehunk"); - - if (!buf) - Sys_Error ("COM_LoadFile: not enough space for %s", path); - - ((byte *)buf)[len] = 0; - - Draw_BeginDisc (); - Sys_FileRead (h, buf, len); - COM_CloseFile (h); - Draw_EndDisc (); - - return buf; -} - -byte *COM_LoadHunkFile (char *path) -{ - return COM_LoadFile (path, 1); -} - -byte *COM_LoadTempFile (char *path) -{ - return COM_LoadFile (path, 2); -} - -void COM_LoadCacheFile (char *path, struct cache_user_s *cu) -{ - loadcache = cu; - COM_LoadFile (path, 3); -} - -// uses temp hunk if larger than bufsize -byte *COM_LoadStackFile (char *path, void *buffer, int bufsize) -{ - byte *buf; - - loadbuf = (byte *)buffer; - loadsize = bufsize; - buf = COM_LoadFile (path, 4); - - return buf; -} - -/* -================= -COM_LoadPackFile - -Takes an explicit (not game tree related) path to a pak file. - -Loads the header and directory, adding the files at the beginning -of the list so they override previous pack files. -================= -*/ -pack_t *COM_LoadPackFile (char *packfile) -{ - dpackheader_t header; - int i; - packfile_t *newfiles; - int numpackfiles; - pack_t *pack; - int packhandle; - dpackfile_t info[MAX_FILES_IN_PACK]; - unsigned short crc; - - if (Sys_FileOpenRead (packfile, &packhandle) == -1) - { -// Con_Printf ("Couldn't open %s\n", packfile); - return NULL; - } - Sys_FileRead (packhandle, (void *)&header, sizeof(header)); - if (header.id[0] != 'P' || header.id[1] != 'A' - || header.id[2] != 'C' || header.id[3] != 'K') - Sys_Error ("%s is not a packfile", packfile); - header.dirofs = LittleLong (header.dirofs); - header.dirlen = LittleLong (header.dirlen); - - numpackfiles = header.dirlen / sizeof(dpackfile_t); - - if (numpackfiles > MAX_FILES_IN_PACK) - Sys_Error ("%s has %i files", packfile, numpackfiles); - - if (numpackfiles != PAK0_COUNT) - com_modified = true; // not the original file - - newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile"); - - Sys_FileSeek (packhandle, header.dirofs); - Sys_FileRead (packhandle, (void *)info, header.dirlen); - -// crc the directory to check for modifications - CRC_Init (&crc); - for (i=0 ; ifilename, packfile); - pack->handle = packhandle; - pack->numfiles = numpackfiles; - pack->files = newfiles; - - Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles); - return pack; -} - - -/* -================ -COM_AddGameDirectory - -Sets com_gamedir, adds the directory to the head of the path, -then loads and adds pak1.pak pak2.pak ... -================ -*/ -void COM_AddGameDirectory (char *dir) -{ - int i; - searchpath_t *search; - pack_t *pak; - char pakfile[MAX_OSPATH]; - - strcpy (com_gamedir, dir); - -// -// add the directory to the search path -// - search = Hunk_Alloc (sizeof(searchpath_t)); - strcpy (search->filename, dir); - search->next = com_searchpaths; - com_searchpaths = search; - -// -// add any pak files in the format pak0.pak pak1.pak, ... -// - for (i=0 ; ; i++) - { - sprintf (pakfile, "%s/pak%i.pak", dir, i); - pak = COM_LoadPackFile (pakfile); - if (!pak) - break; - search = Hunk_Alloc (sizeof(searchpath_t)); - search->pack = pak; - search->next = com_searchpaths; - com_searchpaths = search; - } - -// -// add the contents of the parms.txt file to the end of the command line -// - -} - -/* -================ -COM_InitFilesystem -================ -*/ -void COM_InitFilesystem (void) -{ - int i, j; - char basedir[MAX_OSPATH]; - searchpath_t *search; - -// -// -basedir -// Overrides the system supplied base directory (under GAMENAME) -// - i = COM_CheckParm ("-basedir"); - if (i && i < com_argc-1) - strcpy (basedir, com_argv[i+1]); - else - strcpy (basedir, host_parms.basedir); - - j = strlen (basedir); - - if (j > 0) - { - if ((basedir[j-1] == '\\') || (basedir[j-1] == '/')) - basedir[j-1] = 0; - } - -// -// -cachedir -// Overrides the system supplied cache directory (NULL or /qcache) -// -cachedir - will disable caching. -// - i = COM_CheckParm ("-cachedir"); - if (i && i < com_argc-1) - { - if (com_argv[i+1][0] == '-') - com_cachedir[0] = 0; - else - strcpy (com_cachedir, com_argv[i+1]); - } - else if (host_parms.cachedir) - strcpy (com_cachedir, host_parms.cachedir); - else - com_cachedir[0] = 0; - -// -// start up with GAMENAME by default (id1) -// - COM_AddGameDirectory (va("%s/"GAMENAME, basedir) ); - - if (COM_CheckParm ("-rogue")) - COM_AddGameDirectory (va("%s/rogue", basedir) ); - if (COM_CheckParm ("-hipnotic")) - COM_AddGameDirectory (va("%s/hipnotic", basedir) ); - -// -// -game -// Adds basedir/gamedir as an override game -// - i = COM_CheckParm ("-game"); - if (i && i < com_argc-1) - { - com_modified = true; - COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1])); - } - -// -// -path [] ... -// Fully specifies the exact serach path, overriding the generated one -// - i = COM_CheckParm ("-path"); - if (i) - { - com_modified = true; - com_searchpaths = NULL; - while (++i < com_argc) - { - if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') - break; - - search = Hunk_Alloc (sizeof(searchpath_t)); - if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") ) - { - search->pack = COM_LoadPackFile (com_argv[i]); - if (!search->pack) - Sys_Error ("Couldn't load packfile: %s", com_argv[i]); - } - else - strcpy (search->filename, com_argv[i]); - search->next = com_searchpaths; - com_searchpaths = search; - } - } - - if (COM_CheckParm ("-proghack")) - proghack = true; -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// common.c -- misc functions used in client and server + +#include "quakedef.h" + +#define NUM_SAFE_ARGVS 7 + +static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; +static char *argvdummy = " "; + +static char *safeargvs[NUM_SAFE_ARGVS] = + {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"}; + +cvar_t registered = {"registered","0"}; +cvar_t cmdline = {"cmdline","0", false, true}; + +qboolean com_modified; // set true if using non-id files + +qboolean proghack; + +int static_registered = 1; // only for startup check, then set + +qboolean msg_suppress_1 = 0; + +void COM_InitFilesystem (void); + +// if a packfile directory differs from this, it is assumed to be hacked +#define PAK0_COUNT 339 +#define PAK0_CRC 32981 + +char com_token[1024]; +int com_argc; +char **com_argv; + +#define CMDLINE_LENGTH 256 +char com_cmdline[CMDLINE_LENGTH]; + +qboolean standard_quake = true, rogue, hipnotic; + +// this graphic needs to be in the pak file to use registered features +unsigned short pop[] = +{ + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000 +,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000 +,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600 +,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563 +,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564 +,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564 +,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563 +,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500 +,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200 +,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000 +,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000 +}; + +/* + + +All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources. + +The "base directory" is the path to the directory holding the quake.exe and all game directories. The sys_* files pass this to host_init in quakeparms_t->basedir. This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory. The base directory is +only used during filesystem initialization. + +The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to. This can be overridden with the "-game" command line parameter. The game directory can never be changed while quake is executing. This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't. + +The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines. If there is a cache directory +specified, when a file is found by the normal search path, it will be mirrored +into the cache directory, then opened there. + + + +FIXME: +The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line. + +*/ + +//============================================================================ + + +// ClearLink is used for new headnodes +void ClearLink (link_t *l) +{ + l->prev = l->next = l; +} + +void RemoveLink (link_t *l) +{ + l->next->prev = l->prev; + l->prev->next = l->next; +} + +void InsertLinkBefore (link_t *l, link_t *before) +{ + l->next = before; + l->prev = before->prev; + l->prev->next = l; + l->next->prev = l; +} +void InsertLinkAfter (link_t *l, link_t *after) +{ + l->next = after->next; + l->prev = after; + l->prev->next = l; + l->next->prev = l; +} + +/* +============================================================================ + + LIBRARY REPLACEMENT FUNCTIONS + +============================================================================ +*/ + +void Q_memset (void *dest, int fill, int count) +{ + int i; + + if ( (((long)dest | count) & 3) == 0) + { + count >>= 2; + fill = fill | (fill<<8) | (fill<<16) | (fill<<24); + for (i=0 ; i>=2; + for (i=0 ; i= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + if (!c1) + return 0; // strings are equal +// s1++; +// s2++; + } + + return -1; +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return Q_strncasecmp (s1, s2, 99999); +} + +int Q_atoi (char *str) +{ + int val; + int sign; + int c; + + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val<<4) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val<<4) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val<<4) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + while (1) + { + c = *str++; + if (c <'0' || c > '9') + return val*sign; + val = val*10 + c - '0'; + } + + return 0; +} + + +float Q_atof (char *str) +{ + double val; + int sign; + int c; + int decimal, total; + + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val*16) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val*16) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val*16) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + decimal = -1; + total = 0; + while (1) + { + c = *str++; + if (c == '.') + { + decimal = total; + continue; + } + if (c <'0' || c > '9') + break; + val = val*10 + c - '0'; + total++; + } + + if (decimal == -1) + return val*sign; + while (total > decimal) + { + val /= 10; + total--; + } + + return val*sign; +} + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +qboolean bigendien; + +short (*BigShort) (short l); +short (*LittleShort) (short l); +int (*BigLong) (int l); +int (*LittleLong) (int l); +float (*BigFloat) (float l); +float (*LittleFloat) (float l); + +short ShortSwap (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short ShortNoSwap (short l) +{ + return l; +} + +int LongSwap (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LongNoSwap (int l) +{ + return l; +} + +float FloatSwap (float f) +{ + union + { + float f; + byte b[4]; + } dat1, dat2; + + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} + +float FloatNoSwap (float f) +{ + return f; +} + +/* +============================================================================== + + MESSAGE IO FUNCTIONS + +Handles byte ordering and avoids alignment errors +============================================================================== +*/ + +// +// writing functions +// + +void MSG_WriteChar (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < -128 || c > 127) + Sys_Error ("MSG_WriteChar: range error"); +#endif + + buf = SZ_GetSpace (sb, 1); + buf[0] = c; +} + +void MSG_WriteByte (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < 0 || c > 255) + Sys_Error ("MSG_WriteByte: range error"); +#endif + + buf = SZ_GetSpace (sb, 1); + buf[0] = c; +} + +void MSG_WriteShort (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < ((short)0x8000) || c > (short)0x7fff) + Sys_Error ("MSG_WriteShort: range error"); +#endif + + buf = SZ_GetSpace (sb, 2); + buf[0] = c&0xff; + buf[1] = c>>8; +} + +void MSG_WriteLong (sizebuf_t *sb, int c) +{ + byte *buf; + + buf = SZ_GetSpace (sb, 4); + buf[0] = c&0xff; + buf[1] = (c>>8)&0xff; + buf[2] = (c>>16)&0xff; + buf[3] = c>>24; +} + +void MSG_WriteFloat (sizebuf_t *sb, float f) +{ + union + { + float f; + int l; + } dat; + + + dat.f = f; + dat.l = LittleLong (dat.l); + + SZ_Write (sb, &dat.l, 4); +} + +void MSG_WriteString (sizebuf_t *sb, char *s) +{ + if (!s) + SZ_Write (sb, "", 1); + else + SZ_Write (sb, s, Q_strlen(s)+1); +} + +void MSG_WriteCoord (sizebuf_t *sb, float f) +{ + MSG_WriteShort (sb, (int)(f*8)); +} + +void MSG_WriteAngle (sizebuf_t *sb, float f) +{ + MSG_WriteByte (sb, ((int)f*256/360) & 255); +} + +// +// reading functions +// +int msg_readcount; +qboolean msg_badread; + +void MSG_BeginReading (void) +{ + msg_readcount = 0; + msg_badread = false; +} + +// returns -1 and sets msg_badread if no more characters are available +int MSG_ReadChar (void) +{ + int c; + + if (msg_readcount+1 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (signed char)net_message.data[msg_readcount]; + msg_readcount++; + + return c; +} + +int MSG_ReadByte (void) +{ + int c; + + if (msg_readcount+1 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (unsigned char)net_message.data[msg_readcount]; + msg_readcount++; + + return c; +} + +int MSG_ReadShort (void) +{ + int c; + + if (msg_readcount+2 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (short)(net_message.data[msg_readcount] + + (net_message.data[msg_readcount+1]<<8)); + + msg_readcount += 2; + + return c; +} + +int MSG_ReadLong (void) +{ + int c; + + if (msg_readcount+4 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = net_message.data[msg_readcount] + + (net_message.data[msg_readcount+1]<<8) + + (net_message.data[msg_readcount+2]<<16) + + (net_message.data[msg_readcount+3]<<24); + + msg_readcount += 4; + + return c; +} + +float MSG_ReadFloat (void) +{ + union + { + byte b[4]; + float f; + int l; + } dat; + + dat.b[0] = net_message.data[msg_readcount]; + dat.b[1] = net_message.data[msg_readcount+1]; + dat.b[2] = net_message.data[msg_readcount+2]; + dat.b[3] = net_message.data[msg_readcount+3]; + msg_readcount += 4; + + dat.l = LittleLong (dat.l); + + return dat.f; +} + +char *MSG_ReadString (void) +{ + static char string[2048]; + int l,c; + + l = 0; + do + { + c = MSG_ReadChar (); + if (c == -1 || c == 0) + break; + string[l] = c; + l++; + } while (l < sizeof(string)-1); + + string[l] = 0; + + return string; +} + +float MSG_ReadCoord (void) +{ + return MSG_ReadShort() * (1.0/8); +} + +float MSG_ReadAngle (void) +{ + return MSG_ReadChar() * (360.0/256); +} + + + +//=========================================================================== + +void SZ_Alloc (sizebuf_t *buf, int startsize) +{ + if (startsize < 256) + startsize = 256; + buf->data = Hunk_AllocName (startsize, "sizebuf"); + buf->maxsize = startsize; + buf->cursize = 0; +} + + +void SZ_Free (sizebuf_t *buf) +{ +// Z_Free (buf->data); +// buf->data = NULL; +// buf->maxsize = 0; + buf->cursize = 0; +} + +void SZ_Clear (sizebuf_t *buf) +{ + buf->cursize = 0; +} + +void *SZ_GetSpace (sizebuf_t *buf, int length) +{ + void *data; + + if (buf->cursize + length > buf->maxsize) + { + if (!buf->allowoverflow) + Sys_Error ("SZ_GetSpace: overflow without allowoverflow set"); + + if (length > buf->maxsize) + Sys_Error ("SZ_GetSpace: %i is > full buffer size", length); + + buf->overflowed = true; + Con_Printf ("SZ_GetSpace: overflow"); + SZ_Clear (buf); + } + + data = buf->data + buf->cursize; + buf->cursize += length; + + return data; +} + +void SZ_Write (sizebuf_t *buf, void *data, int length) +{ + Q_memcpy (SZ_GetSpace(buf,length),data,length); +} + +void SZ_Print (sizebuf_t *buf, char *data) +{ + int len; + + len = Q_strlen(data)+1; + +// byte * cast to keep VC++ happy + if (buf->data[buf->cursize-1]) + Q_memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0 + else + Q_memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0 +} + + +//============================================================================ + + +/* +============ +COM_SkipPath +============ +*/ +char *COM_SkipPath (char *pathname) +{ + char *last; + + last = pathname; + while (*pathname) + { + if (*pathname=='/') + last = pathname+1; + pathname++; + } + return last; +} + +/* +============ +COM_StripExtension +============ +*/ +void COM_StripExtension (char *in, char *out) +{ + while (*in && *in != '.') + *out++ = *in++; + *out = 0; +} + +/* +============ +COM_FileExtension +============ +*/ +char *COM_FileExtension (char *in) +{ + static char exten[8]; + int i; + + while (*in && *in != '.') + in++; + if (!*in) + return ""; + in++; + for (i=0 ; i<7 && *in ; i++,in++) + exten[i] = *in; + exten[i] = 0; + return exten; +} + +/* +============ +COM_FileBase +============ +*/ +void COM_FileBase (char *in, char *out) +{ + char *s, *s2; + + s = in + strlen(in) - 1; + + while (s != in && *s != '.') + s--; + + for (s2 = s ; *s2 && *s2 != '/' ; s2--) + ; + + if (s-s2 < 2) + strcpy (out,"?model?"); + else + { + s--; + strncpy (out,s2+1, s-s2); + out[s-s2] = 0; + } +} + + +/* +================== +COM_DefaultExtension +================== +*/ +void COM_DefaultExtension (char *path, char *extension) +{ + char *src; +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen(path) - 1; + + while (*src != '/' && src != path) + { + if (*src == '.') + return; // it has an extension + src--; + } + + strcat (path, extension); +} + + +/* +============== +COM_Parse + +Parse a token out of a string +============== +*/ +char *COM_Parse (char *data) +{ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if (!data) + return NULL; + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') + { + if (c == 0) + return NULL; // end of file; + data++; + } + +// skip // comments + if (c=='/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if (c == '\"') + { + data++; + while (1) + { + c = *data++; + if (c=='\"' || !c) + { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } + } + +// parse single characters + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + { + com_token[len] = c; + len++; + com_token[len] = 0; + return data+1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + break; + } while (c>32); + + com_token[len] = 0; + return data; +} + + +/* +================ +COM_CheckParm + +Returns the position (1 to argc-1) in the program's argument list +where the given parameter apears, or 0 if not present +================ +*/ +int COM_CheckParm (char *parm) +{ + int i; + + for (i=1 ; inext) + { + if (s->pack) + { + Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles); + } + else + Con_Printf ("%s\n", s->filename); + } +} + +/* +============ +COM_WriteFile + +The filename will be prefixed by the current game directory +============ +*/ +void COM_WriteFile (char *filename, void *data, int len) +{ + int handle; + char name[MAX_OSPATH]; + + sprintf (name, "%s/%s", com_gamedir, filename); + + handle = Sys_FileOpenWrite (name); + if (handle == -1) + { + Sys_Printf ("COM_WriteFile: failed on %s\n", name); + return; + } + + Sys_Printf ("COM_WriteFile: %s\n", name); + Sys_FileWrite (handle, data, len); + Sys_FileClose (handle); +} + + +/* +============ +COM_CreatePath + +Only used for CopyFile +============ +*/ +void COM_CreatePath (char *path) +{ + char *ofs; + + for (ofs = path+1 ; *ofs ; ofs++) + { + if (*ofs == '/') + { // create the directory + *ofs = 0; + Sys_mkdir (path); + *ofs = '/'; + } + } +} + + +/* +=========== +COM_CopyFile + +Copies a file over from the net to the local cache, creating any directories +needed. This is for the convenience of developers using ISDN from home. +=========== +*/ +void COM_CopyFile (char *netpath, char *cachepath) +{ + int in, out; + int remaining, count; + char buf[4096]; + + remaining = Sys_FileOpenRead (netpath, &in); + COM_CreatePath (cachepath); // create directories up to the cache file + out = Sys_FileOpenWrite (cachepath); + + while (remaining) + { + if (remaining < sizeof(buf)) + count = remaining; + else + count = sizeof(buf); + Sys_FileRead (in, buf, count); + Sys_FileWrite (out, buf, count); + remaining -= count; + } + + Sys_FileClose (in); + Sys_FileClose (out); +} + +/* +=========== +COM_FindFile + +Finds the file in the search path. +Sets com_filesize and one of handle or file +=========== +*/ +int COM_FindFile (char *filename, int *handle, FILE **file) +{ + searchpath_t *search; + char netpath[MAX_OSPATH]; + char cachepath[MAX_OSPATH]; + pack_t *pak; + int i; + int findtime, cachetime; + + if (file && handle) + Sys_Error ("COM_FindFile: both handle and file set"); + if (!file && !handle) + Sys_Error ("COM_FindFile: neither handle or file set"); + +// +// search through the path, one element at a time +// + search = com_searchpaths; + if (proghack) + { // gross hack to use quake 1 progs with quake 2 maps + if (!strcmp(filename, "progs.dat")) + search = search->next; + } + + for ( ; search ; search = search->next) + { + // is the element a pak file? + if (search->pack) + { + // look through all the pak file elements + pak = search->pack; + for (i=0 ; inumfiles ; i++) + if (!strcmp (pak->files[i].name, filename)) + { // found it! + Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename); + if (handle) + { + *handle = pak->handle; + Sys_FileSeek (pak->handle, pak->files[i].filepos); + } + else + { // open a new file on the pakfile + *file = fopen (pak->filename, "rb"); + if (*file) + fseek (*file, pak->files[i].filepos, SEEK_SET); + } + com_filesize = pak->files[i].filelen; + return com_filesize; + } + } + else + { + // check a file in the directory tree + if (!static_registered) + { // if not a registered version, don't ever go beyond base + if ( strchr (filename, '/') || strchr (filename,'\\')) + continue; + } + + sprintf (netpath, "%s/%s",search->filename, filename); + + findtime = Sys_FileTime (netpath); + if (findtime == -1) + continue; + + // see if the file needs to be updated in the cache + if (!com_cachedir[0]) + strcpy (cachepath, netpath); + else + { +#if defined(_WIN32) + if ((strlen(netpath) < 2) || (netpath[1] != ':')) + sprintf (cachepath,"%s%s", com_cachedir, netpath); + else + sprintf (cachepath,"%s%s", com_cachedir, netpath+2); +#else + sprintf (cachepath,"%s%s", com_cachedir, netpath); +#endif + + cachetime = Sys_FileTime (cachepath); + + if (cachetime < findtime) + COM_CopyFile (netpath, cachepath); + strcpy (netpath, cachepath); + } + + Sys_Printf ("FindFile: %s\n",netpath); + com_filesize = Sys_FileOpenRead (netpath, &i); + if (handle) + *handle = i; + else + { + Sys_FileClose (i); + *file = fopen (netpath, "rb"); + } + return com_filesize; + } + + } + + Sys_Printf ("FindFile: can't find %s\n", filename); + + if (handle) + *handle = -1; + else + *file = NULL; + com_filesize = -1; + return -1; +} + + +/* +=========== +COM_OpenFile + +filename never has a leading slash, but may contain directory walks +returns a handle and a length +it may actually be inside a pak file +=========== +*/ +int COM_OpenFile (char *filename, int *handle) +{ + return COM_FindFile (filename, handle, NULL); +} + +/* +=========== +COM_FOpenFile + +If the requested file is inside a packfile, a new FILE * will be opened +into the file. +=========== +*/ +int COM_FOpenFile (char *filename, FILE **file) +{ + return COM_FindFile (filename, NULL, file); +} + +/* +============ +COM_CloseFile + +If it is a pak file handle, don't really close it +============ +*/ +void COM_CloseFile (int h) +{ + searchpath_t *s; + + for (s = com_searchpaths ; s ; s=s->next) + if (s->pack && s->pack->handle == h) + return; + + Sys_FileClose (h); +} + + +/* +============ +COM_LoadFile + +Filename are reletive to the quake directory. +Allways appends a 0 byte. +============ +*/ +cache_user_t *loadcache; +byte *loadbuf; +int loadsize; +byte *COM_LoadFile (char *path, int usehunk) +{ + int h; + byte *buf; + char base[32]; + int len; + + buf = NULL; // quiet compiler warning + +// look for it in the filesystem or pack files + len = COM_OpenFile (path, &h); + if (h == -1) + return NULL; + +// extract the filename base name for hunk tag + COM_FileBase (path, base); + + if (usehunk == 1) + buf = Hunk_AllocName (len+1, base); + else if (usehunk == 2) + buf = Hunk_TempAlloc (len+1); + else if (usehunk == 0) + buf = Z_Malloc (len+1); + else if (usehunk == 3) + buf = Cache_Alloc (loadcache, len+1, base); + else if (usehunk == 4) + { + if (len+1 > loadsize) + buf = Hunk_TempAlloc (len+1); + else + buf = loadbuf; + } + else + Sys_Error ("COM_LoadFile: bad usehunk"); + + if (!buf) + Sys_Error ("COM_LoadFile: not enough space for %s", path); + + ((byte *)buf)[len] = 0; + + Draw_BeginDisc (); + Sys_FileRead (h, buf, len); + COM_CloseFile (h); + Draw_EndDisc (); + + return buf; +} + +byte *COM_LoadHunkFile (char *path) +{ + return COM_LoadFile (path, 1); +} + +byte *COM_LoadTempFile (char *path) +{ + return COM_LoadFile (path, 2); +} + +void COM_LoadCacheFile (char *path, struct cache_user_s *cu) +{ + loadcache = cu; + COM_LoadFile (path, 3); +} + +// uses temp hunk if larger than bufsize +byte *COM_LoadStackFile (char *path, void *buffer, int bufsize) +{ + byte *buf; + + loadbuf = (byte *)buffer; + loadsize = bufsize; + buf = COM_LoadFile (path, 4); + + return buf; +} + +/* +================= +COM_LoadPackFile + +Takes an explicit (not game tree related) path to a pak file. + +Loads the header and directory, adding the files at the beginning +of the list so they override previous pack files. +================= +*/ +pack_t *COM_LoadPackFile (char *packfile) +{ + dpackheader_t header; + int i; + packfile_t *newfiles; + int numpackfiles; + pack_t *pack; + int packhandle; + dpackfile_t info[MAX_FILES_IN_PACK]; + unsigned short crc; + + if (Sys_FileOpenRead (packfile, &packhandle) == -1) + { +// Con_Printf ("Couldn't open %s\n", packfile); + return NULL; + } + Sys_FileRead (packhandle, (void *)&header, sizeof(header)); + if (header.id[0] != 'P' || header.id[1] != 'A' + || header.id[2] != 'C' || header.id[3] != 'K') + Sys_Error ("%s is not a packfile", packfile); + header.dirofs = LittleLong (header.dirofs); + header.dirlen = LittleLong (header.dirlen); + + numpackfiles = header.dirlen / sizeof(dpackfile_t); + + if (numpackfiles > MAX_FILES_IN_PACK) + Sys_Error ("%s has %i files", packfile, numpackfiles); + + if (numpackfiles != PAK0_COUNT) + com_modified = true; // not the original file + + newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile"); + + Sys_FileSeek (packhandle, header.dirofs); + Sys_FileRead (packhandle, (void *)info, header.dirlen); + +// crc the directory to check for modifications + CRC_Init (&crc); + for (i=0 ; ifilename, packfile); + pack->handle = packhandle; + pack->numfiles = numpackfiles; + pack->files = newfiles; + + Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles); + return pack; +} + + +/* +================ +COM_AddGameDirectory + +Sets com_gamedir, adds the directory to the head of the path, +then loads and adds pak1.pak pak2.pak ... +================ +*/ +void COM_AddGameDirectory (char *dir) +{ + int i; + searchpath_t *search; + pack_t *pak; + char pakfile[MAX_OSPATH]; + + strcpy (com_gamedir, dir); + +// +// add the directory to the search path +// + search = Hunk_Alloc (sizeof(searchpath_t)); + strcpy (search->filename, dir); + search->next = com_searchpaths; + com_searchpaths = search; + +// +// add any pak files in the format pak0.pak pak1.pak, ... +// + for (i=0 ; ; i++) + { + sprintf (pakfile, "%s/pak%i.pak", dir, i); + pak = COM_LoadPackFile (pakfile); + if (!pak) + break; + search = Hunk_Alloc (sizeof(searchpath_t)); + search->pack = pak; + search->next = com_searchpaths; + com_searchpaths = search; + } + +// +// add the contents of the parms.txt file to the end of the command line +// + +} + +/* +================ +COM_InitFilesystem +================ +*/ +void COM_InitFilesystem (void) +{ + int i, j; + char basedir[MAX_OSPATH]; + searchpath_t *search; + +// +// -basedir +// Overrides the system supplied base directory (under GAMENAME) +// + i = COM_CheckParm ("-basedir"); + if (i && i < com_argc-1) + strcpy (basedir, com_argv[i+1]); + else + strcpy (basedir, host_parms.basedir); + + j = strlen (basedir); + + if (j > 0) + { + if ((basedir[j-1] == '\\') || (basedir[j-1] == '/')) + basedir[j-1] = 0; + } + +// +// -cachedir +// Overrides the system supplied cache directory (NULL or /qcache) +// -cachedir - will disable caching. +// + i = COM_CheckParm ("-cachedir"); + if (i && i < com_argc-1) + { + if (com_argv[i+1][0] == '-') + com_cachedir[0] = 0; + else + strcpy (com_cachedir, com_argv[i+1]); + } + else if (host_parms.cachedir) + strcpy (com_cachedir, host_parms.cachedir); + else + com_cachedir[0] = 0; + +// +// start up with GAMENAME by default (id1) +// + COM_AddGameDirectory (va("%s/"GAMENAME, basedir) ); + + if (COM_CheckParm ("-rogue")) + COM_AddGameDirectory (va("%s/rogue", basedir) ); + if (COM_CheckParm ("-hipnotic")) + COM_AddGameDirectory (va("%s/hipnotic", basedir) ); + +// +// -game +// Adds basedir/gamedir as an override game +// + i = COM_CheckParm ("-game"); + if (i && i < com_argc-1) + { + com_modified = true; + COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1])); + } + +// +// -path [] ... +// Fully specifies the exact serach path, overriding the generated one +// + i = COM_CheckParm ("-path"); + if (i) + { + com_modified = true; + com_searchpaths = NULL; + while (++i < com_argc) + { + if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') + break; + + search = Hunk_Alloc (sizeof(searchpath_t)); + if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") ) + { + search->pack = COM_LoadPackFile (com_argv[i]); + if (!search->pack) + Sys_Error ("Couldn't load packfile: %s", com_argv[i]); + } + else + strcpy (search->filename, com_argv[i]); + search->next = com_searchpaths; + com_searchpaths = search; + } + } + + if (COM_CheckParm ("-proghack")) + proghack = true; +} + + diff --git a/WinQuake/common.h b/WinQuake/common.h index 87d4a55..0a2f874 100644 --- a/WinQuake/common.h +++ b/WinQuake/common.h @@ -1,183 +1,183 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// comndef.h -- general definitions - -#if !defined BYTE_DEFINED -typedef unsigned char byte; -#define BYTE_DEFINED 1 -#endif - -#undef true -#undef false - -typedef enum {false, true} qboolean; - -//============================================================================ - -typedef struct sizebuf_s -{ - qboolean allowoverflow; // if false, do a Sys_Error - qboolean overflowed; // set to true if the buffer size failed - byte *data; - int maxsize; - int cursize; -} sizebuf_t; - -void SZ_Alloc (sizebuf_t *buf, int startsize); -void SZ_Free (sizebuf_t *buf); -void SZ_Clear (sizebuf_t *buf); -void *SZ_GetSpace (sizebuf_t *buf, int length); -void SZ_Write (sizebuf_t *buf, void *data, int length); -void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf - -//============================================================================ - -typedef struct link_s -{ - struct link_s *prev, *next; -} link_t; - - -void ClearLink (link_t *l); -void RemoveLink (link_t *l); -void InsertLinkBefore (link_t *l, link_t *before); -void InsertLinkAfter (link_t *l, link_t *after); - -// (type *)STRUCT_FROM_LINK(link_t *link, type, member) -// ent = STRUCT_FROM_LINK(link,entity_t,order) -// FIXME: remove this mess! -#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) - -//============================================================================ - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define Q_MAXCHAR ((char)0x7f) -#define Q_MAXSHORT ((short)0x7fff) -#define Q_MAXINT ((int)0x7fffffff) -#define Q_MAXLONG ((int)0x7fffffff) -#define Q_MAXFLOAT ((int)0x7fffffff) - -#define Q_MINCHAR ((char)0x80) -#define Q_MINSHORT ((short)0x8000) -#define Q_MININT ((int)0x80000000) -#define Q_MINLONG ((int)0x80000000) -#define Q_MINFLOAT ((int)0x7fffffff) - -//============================================================================ - -extern qboolean bigendien; - -extern short (*BigShort) (short l); -extern short (*LittleShort) (short l); -extern int (*BigLong) (int l); -extern int (*LittleLong) (int l); -extern float (*BigFloat) (float l); -extern float (*LittleFloat) (float l); - -//============================================================================ - -void MSG_WriteChar (sizebuf_t *sb, int c); -void MSG_WriteByte (sizebuf_t *sb, int c); -void MSG_WriteShort (sizebuf_t *sb, int c); -void MSG_WriteLong (sizebuf_t *sb, int c); -void MSG_WriteFloat (sizebuf_t *sb, float f); -void MSG_WriteString (sizebuf_t *sb, char *s); -void MSG_WriteCoord (sizebuf_t *sb, float f); -void MSG_WriteAngle (sizebuf_t *sb, float f); - -extern int msg_readcount; -extern qboolean msg_badread; // set if a read goes beyond end of message - -void MSG_BeginReading (void); -int MSG_ReadChar (void); -int MSG_ReadByte (void); -int MSG_ReadShort (void); -int MSG_ReadLong (void); -float MSG_ReadFloat (void); -char *MSG_ReadString (void); - -float MSG_ReadCoord (void); -float MSG_ReadAngle (void); - -//============================================================================ - -void Q_memset (void *dest, int fill, int count); -void Q_memcpy (void *dest, void *src, int count); -int Q_memcmp (void *m1, void *m2, int count); -void Q_strcpy (char *dest, char *src); -void Q_strncpy (char *dest, char *src, int count); -int Q_strlen (char *str); -char *Q_strrchr (char *s, char c); -void Q_strcat (char *dest, char *src); -int Q_strcmp (char *s1, char *s2); -int Q_strncmp (char *s1, char *s2, int count); -int Q_strcasecmp (char *s1, char *s2); -int Q_strncasecmp (char *s1, char *s2, int n); -int Q_atoi (char *str); -float Q_atof (char *str); - -//============================================================================ - -extern char com_token[1024]; -extern qboolean com_eof; - -char *COM_Parse (char *data); - - -extern int com_argc; -extern char **com_argv; - -int COM_CheckParm (char *parm); -void COM_Init (char *path); -void COM_InitArgv (int argc, char **argv); - -char *COM_SkipPath (char *pathname); -void COM_StripExtension (char *in, char *out); -void COM_FileBase (char *in, char *out); -void COM_DefaultExtension (char *path, char *extension); - -char *va(char *format, ...); -// does a varargs printf into a temp buffer - - -//============================================================================ - -extern int com_filesize; -struct cache_user_s; - -extern char com_gamedir[MAX_OSPATH]; - -void COM_WriteFile (char *filename, void *data, int len); -int COM_OpenFile (char *filename, int *hndl); -int COM_FOpenFile (char *filename, FILE **file); -void COM_CloseFile (int h); - -byte *COM_LoadStackFile (char *path, void *buffer, int bufsize); -byte *COM_LoadTempFile (char *path); -byte *COM_LoadHunkFile (char *path); -void COM_LoadCacheFile (char *path, struct cache_user_s *cu); - - -extern struct cvar_s registered; - -extern qboolean standard_quake, rogue, hipnotic; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// comndef.h -- general definitions + +#if !defined BYTE_DEFINED +typedef unsigned char byte; +#define BYTE_DEFINED 1 +#endif + +#undef true +#undef false + +typedef enum {false, true} qboolean; + +//============================================================================ + +typedef struct sizebuf_s +{ + qboolean allowoverflow; // if false, do a Sys_Error + qboolean overflowed; // set to true if the buffer size failed + byte *data; + int maxsize; + int cursize; +} sizebuf_t; + +void SZ_Alloc (sizebuf_t *buf, int startsize); +void SZ_Free (sizebuf_t *buf); +void SZ_Clear (sizebuf_t *buf); +void *SZ_GetSpace (sizebuf_t *buf, int length); +void SZ_Write (sizebuf_t *buf, void *data, int length); +void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf + +//============================================================================ + +typedef struct link_s +{ + struct link_s *prev, *next; +} link_t; + + +void ClearLink (link_t *l); +void RemoveLink (link_t *l); +void InsertLinkBefore (link_t *l, link_t *before); +void InsertLinkAfter (link_t *l, link_t *after); + +// (type *)STRUCT_FROM_LINK(link_t *link, type, member) +// ent = STRUCT_FROM_LINK(link,entity_t,order) +// FIXME: remove this mess! +#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) + +//============================================================================ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define Q_MAXCHAR ((char)0x7f) +#define Q_MAXSHORT ((short)0x7fff) +#define Q_MAXINT ((int)0x7fffffff) +#define Q_MAXLONG ((int)0x7fffffff) +#define Q_MAXFLOAT ((int)0x7fffffff) + +#define Q_MINCHAR ((char)0x80) +#define Q_MINSHORT ((short)0x8000) +#define Q_MININT ((int)0x80000000) +#define Q_MINLONG ((int)0x80000000) +#define Q_MINFLOAT ((int)0x7fffffff) + +//============================================================================ + +extern qboolean bigendien; + +extern short (*BigShort) (short l); +extern short (*LittleShort) (short l); +extern int (*BigLong) (int l); +extern int (*LittleLong) (int l); +extern float (*BigFloat) (float l); +extern float (*LittleFloat) (float l); + +//============================================================================ + +void MSG_WriteChar (sizebuf_t *sb, int c); +void MSG_WriteByte (sizebuf_t *sb, int c); +void MSG_WriteShort (sizebuf_t *sb, int c); +void MSG_WriteLong (sizebuf_t *sb, int c); +void MSG_WriteFloat (sizebuf_t *sb, float f); +void MSG_WriteString (sizebuf_t *sb, char *s); +void MSG_WriteCoord (sizebuf_t *sb, float f); +void MSG_WriteAngle (sizebuf_t *sb, float f); + +extern int msg_readcount; +extern qboolean msg_badread; // set if a read goes beyond end of message + +void MSG_BeginReading (void); +int MSG_ReadChar (void); +int MSG_ReadByte (void); +int MSG_ReadShort (void); +int MSG_ReadLong (void); +float MSG_ReadFloat (void); +char *MSG_ReadString (void); + +float MSG_ReadCoord (void); +float MSG_ReadAngle (void); + +//============================================================================ + +void Q_memset (void *dest, int fill, int count); +void Q_memcpy (void *dest, void *src, int count); +int Q_memcmp (void *m1, void *m2, int count); +void Q_strcpy (char *dest, char *src); +void Q_strncpy (char *dest, char *src, int count); +int Q_strlen (char *str); +char *Q_strrchr (char *s, char c); +void Q_strcat (char *dest, char *src); +int Q_strcmp (char *s1, char *s2); +int Q_strncmp (char *s1, char *s2, int count); +int Q_strcasecmp (char *s1, char *s2); +int Q_strncasecmp (char *s1, char *s2, int n); +int Q_atoi (char *str); +float Q_atof (char *str); + +//============================================================================ + +extern char com_token[1024]; +extern qboolean com_eof; + +char *COM_Parse (char *data); + + +extern int com_argc; +extern char **com_argv; + +int COM_CheckParm (char *parm); +void COM_Init (char *path); +void COM_InitArgv (int argc, char **argv); + +char *COM_SkipPath (char *pathname); +void COM_StripExtension (char *in, char *out); +void COM_FileBase (char *in, char *out); +void COM_DefaultExtension (char *path, char *extension); + +char *va(char *format, ...); +// does a varargs printf into a temp buffer + + +//============================================================================ + +extern int com_filesize; +struct cache_user_s; + +extern char com_gamedir[MAX_OSPATH]; + +void COM_WriteFile (char *filename, void *data, int len); +int COM_OpenFile (char *filename, int *hndl); +int COM_FOpenFile (char *filename, FILE **file); +void COM_CloseFile (int h); + +byte *COM_LoadStackFile (char *path, void *buffer, int bufsize); +byte *COM_LoadTempFile (char *path); +byte *COM_LoadHunkFile (char *path); +void COM_LoadCacheFile (char *path, struct cache_user_s *cu); + + +extern struct cvar_s registered; + +extern qboolean standard_quake, rogue, hipnotic; diff --git a/WinQuake/conproc.c b/WinQuake/conproc.c index 43c20ca..780f540 100644 --- a/WinQuake/conproc.c +++ b/WinQuake/conproc.c @@ -1,365 +1,365 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// conproc.c - -#include -#include "conproc.h" -#include "quakedef.h" - -HANDLE heventDone; -HANDLE hfileBuffer; -HANDLE heventChildSend; -HANDLE heventParentSend; -HANDLE hStdout; -HANDLE hStdin; - -DWORD RequestProc (DWORD dwNichts); -LPVOID GetMappedBuffer (HANDLE hfileBuffer); -void ReleaseMappedBuffer (LPVOID pBuffer); -BOOL GetScreenBufferLines (int *piLines); -BOOL SetScreenBufferLines (int iLines); -BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine); -BOOL WriteText (LPCTSTR szText); -int CharToCode (char c); -BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy); - - -void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild) -{ - DWORD dwID; - CONSOLE_SCREEN_BUFFER_INFO info; - int wheight, wwidth; - -// ignore if we don't have all the events. - if (!hFile || !heventParent || !heventChild) - return; - - hfileBuffer = hFile; - heventParentSend = heventParent; - heventChildSend = heventChild; - -// so we'll know when to go away. - heventDone = CreateEvent (NULL, FALSE, FALSE, NULL); - - if (!heventDone) - { - Con_SafePrintf ("Couldn't create heventDone\n"); - return; - } - - if (!CreateThread (NULL, - 0, - (LPTHREAD_START_ROUTINE) RequestProc, - 0, - 0, - &dwID)) - { - CloseHandle (heventDone); - Con_SafePrintf ("Couldn't create QHOST thread\n"); - return; - } - -// save off the input/output handles. - hStdout = GetStdHandle (STD_OUTPUT_HANDLE); - hStdin = GetStdHandle (STD_INPUT_HANDLE); - -// force 80 character width, at least 25 character height - SetConsoleCXCY (hStdout, 80, 25); -} - - -void DeinitConProc (void) -{ - if (heventDone) - SetEvent (heventDone); -} - - -DWORD RequestProc (DWORD dwNichts) -{ - int *pBuffer; - DWORD dwRet; - HANDLE heventWait[2]; - int iBeginLine, iEndLine; - - heventWait[0] = heventParentSend; - heventWait[1] = heventDone; - - while (1) - { - dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE); - - // heventDone fired, so we're exiting. - if (dwRet == WAIT_OBJECT_0 + 1) - break; - - pBuffer = (int *) GetMappedBuffer (hfileBuffer); - - // hfileBuffer is invalid. Just leave. - if (!pBuffer) - { - Con_SafePrintf ("Invalid hfileBuffer\n"); - break; - } - - switch (pBuffer[0]) - { - case CCOM_WRITE_TEXT: - // Param1 : Text - pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1)); - break; - - case CCOM_GET_TEXT: - // Param1 : Begin line - // Param2 : End line - iBeginLine = pBuffer[1]; - iEndLine = pBuffer[2]; - pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine, - iEndLine); - break; - - case CCOM_GET_SCR_LINES: - // No params - pBuffer[0] = GetScreenBufferLines (&pBuffer[1]); - break; - - case CCOM_SET_SCR_LINES: - // Param1 : Number of lines - pBuffer[0] = SetScreenBufferLines (pBuffer[1]); - break; - } - - ReleaseMappedBuffer (pBuffer); - SetEvent (heventChildSend); - } - - return 0; -} - - -LPVOID GetMappedBuffer (HANDLE hfileBuffer) -{ - LPVOID pBuffer; - - pBuffer = MapViewOfFile (hfileBuffer, - FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - - return pBuffer; -} - - -void ReleaseMappedBuffer (LPVOID pBuffer) -{ - UnmapViewOfFile (pBuffer); -} - - -BOOL GetScreenBufferLines (int *piLines) -{ - CONSOLE_SCREEN_BUFFER_INFO info; - BOOL bRet; - - bRet = GetConsoleScreenBufferInfo (hStdout, &info); - - if (bRet) - *piLines = info.dwSize.Y; - - return bRet; -} - - -BOOL SetScreenBufferLines (int iLines) -{ - - return SetConsoleCXCY (hStdout, 80, iLines); -} - - -BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine) -{ - COORD coord; - DWORD dwRead; - BOOL bRet; - - coord.X = 0; - coord.Y = iBeginLine; - - bRet = ReadConsoleOutputCharacter( - hStdout, - pszText, - 80 * (iEndLine - iBeginLine + 1), - coord, - &dwRead); - - // Make sure it's null terminated. - if (bRet) - pszText[dwRead] = '\0'; - - return bRet; -} - - -BOOL WriteText (LPCTSTR szText) -{ - DWORD dwWritten; - INPUT_RECORD rec; - char upper, *sz; - - sz = (LPTSTR) szText; - - while (*sz) - { - // 13 is the code for a carriage return (\n) instead of 10. - if (*sz == 10) - *sz = 13; - - upper = toupper(*sz); - - rec.EventType = KEY_EVENT; - rec.Event.KeyEvent.bKeyDown = TRUE; - rec.Event.KeyEvent.wRepeatCount = 1; - rec.Event.KeyEvent.wVirtualKeyCode = upper; - rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz); - rec.Event.KeyEvent.uChar.AsciiChar = *sz; - rec.Event.KeyEvent.uChar.UnicodeChar = *sz; - rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0; - - WriteConsoleInput( - hStdin, - &rec, - 1, - &dwWritten); - - rec.Event.KeyEvent.bKeyDown = FALSE; - - WriteConsoleInput( - hStdin, - &rec, - 1, - &dwWritten); - - sz++; - } - - return TRUE; -} - - -int CharToCode (char c) -{ - char upper; - - upper = toupper(c); - - switch (c) - { - case 13: - return 28; - - default: - break; - } - - if (isalpha(c)) - return (30 + upper - 65); - - if (isdigit(c)) - return (1 + upper - 47); - - return c; -} - - -BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy) -{ - CONSOLE_SCREEN_BUFFER_INFO info; - COORD coordMax; - - coordMax = GetLargestConsoleWindowSize(hStdout); - - if (cy > coordMax.Y) - cy = coordMax.Y; - - if (cx > coordMax.X) - cx = coordMax.X; - - if (!GetConsoleScreenBufferInfo(hStdout, &info)) - return FALSE; - -// height - info.srWindow.Left = 0; - info.srWindow.Right = info.dwSize.X - 1; - info.srWindow.Top = 0; - info.srWindow.Bottom = cy - 1; - - if (cy < info.dwSize.Y) - { - if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) - return FALSE; - - info.dwSize.Y = cy; - - if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) - return FALSE; - } - else if (cy > info.dwSize.Y) - { - info.dwSize.Y = cy; - - if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) - return FALSE; - - if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) - return FALSE; - } - - if (!GetConsoleScreenBufferInfo(hStdout, &info)) - return FALSE; - -// width - info.srWindow.Left = 0; - info.srWindow.Right = cx - 1; - info.srWindow.Top = 0; - info.srWindow.Bottom = info.dwSize.Y - 1; - - if (cx < info.dwSize.X) - { - if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) - return FALSE; - - info.dwSize.X = cx; - - if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) - return FALSE; - } - else if (cx > info.dwSize.X) - { - info.dwSize.X = cx; - - if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) - return FALSE; - - if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) - return FALSE; - } - - return TRUE; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// conproc.c + +#include +#include "conproc.h" +#include "quakedef.h" + +HANDLE heventDone; +HANDLE hfileBuffer; +HANDLE heventChildSend; +HANDLE heventParentSend; +HANDLE hStdout; +HANDLE hStdin; + +DWORD RequestProc (DWORD dwNichts); +LPVOID GetMappedBuffer (HANDLE hfileBuffer); +void ReleaseMappedBuffer (LPVOID pBuffer); +BOOL GetScreenBufferLines (int *piLines); +BOOL SetScreenBufferLines (int iLines); +BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine); +BOOL WriteText (LPCTSTR szText); +int CharToCode (char c); +BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy); + + +void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild) +{ + DWORD dwID; + CONSOLE_SCREEN_BUFFER_INFO info; + int wheight, wwidth; + +// ignore if we don't have all the events. + if (!hFile || !heventParent || !heventChild) + return; + + hfileBuffer = hFile; + heventParentSend = heventParent; + heventChildSend = heventChild; + +// so we'll know when to go away. + heventDone = CreateEvent (NULL, FALSE, FALSE, NULL); + + if (!heventDone) + { + Con_SafePrintf ("Couldn't create heventDone\n"); + return; + } + + if (!CreateThread (NULL, + 0, + (LPTHREAD_START_ROUTINE) RequestProc, + 0, + 0, + &dwID)) + { + CloseHandle (heventDone); + Con_SafePrintf ("Couldn't create QHOST thread\n"); + return; + } + +// save off the input/output handles. + hStdout = GetStdHandle (STD_OUTPUT_HANDLE); + hStdin = GetStdHandle (STD_INPUT_HANDLE); + +// force 80 character width, at least 25 character height + SetConsoleCXCY (hStdout, 80, 25); +} + + +void DeinitConProc (void) +{ + if (heventDone) + SetEvent (heventDone); +} + + +DWORD RequestProc (DWORD dwNichts) +{ + int *pBuffer; + DWORD dwRet; + HANDLE heventWait[2]; + int iBeginLine, iEndLine; + + heventWait[0] = heventParentSend; + heventWait[1] = heventDone; + + while (1) + { + dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE); + + // heventDone fired, so we're exiting. + if (dwRet == WAIT_OBJECT_0 + 1) + break; + + pBuffer = (int *) GetMappedBuffer (hfileBuffer); + + // hfileBuffer is invalid. Just leave. + if (!pBuffer) + { + Con_SafePrintf ("Invalid hfileBuffer\n"); + break; + } + + switch (pBuffer[0]) + { + case CCOM_WRITE_TEXT: + // Param1 : Text + pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1)); + break; + + case CCOM_GET_TEXT: + // Param1 : Begin line + // Param2 : End line + iBeginLine = pBuffer[1]; + iEndLine = pBuffer[2]; + pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine, + iEndLine); + break; + + case CCOM_GET_SCR_LINES: + // No params + pBuffer[0] = GetScreenBufferLines (&pBuffer[1]); + break; + + case CCOM_SET_SCR_LINES: + // Param1 : Number of lines + pBuffer[0] = SetScreenBufferLines (pBuffer[1]); + break; + } + + ReleaseMappedBuffer (pBuffer); + SetEvent (heventChildSend); + } + + return 0; +} + + +LPVOID GetMappedBuffer (HANDLE hfileBuffer) +{ + LPVOID pBuffer; + + pBuffer = MapViewOfFile (hfileBuffer, + FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + + return pBuffer; +} + + +void ReleaseMappedBuffer (LPVOID pBuffer) +{ + UnmapViewOfFile (pBuffer); +} + + +BOOL GetScreenBufferLines (int *piLines) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + BOOL bRet; + + bRet = GetConsoleScreenBufferInfo (hStdout, &info); + + if (bRet) + *piLines = info.dwSize.Y; + + return bRet; +} + + +BOOL SetScreenBufferLines (int iLines) +{ + + return SetConsoleCXCY (hStdout, 80, iLines); +} + + +BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine) +{ + COORD coord; + DWORD dwRead; + BOOL bRet; + + coord.X = 0; + coord.Y = iBeginLine; + + bRet = ReadConsoleOutputCharacter( + hStdout, + pszText, + 80 * (iEndLine - iBeginLine + 1), + coord, + &dwRead); + + // Make sure it's null terminated. + if (bRet) + pszText[dwRead] = '\0'; + + return bRet; +} + + +BOOL WriteText (LPCTSTR szText) +{ + DWORD dwWritten; + INPUT_RECORD rec; + char upper, *sz; + + sz = (LPTSTR) szText; + + while (*sz) + { + // 13 is the code for a carriage return (\n) instead of 10. + if (*sz == 10) + *sz = 13; + + upper = toupper(*sz); + + rec.EventType = KEY_EVENT; + rec.Event.KeyEvent.bKeyDown = TRUE; + rec.Event.KeyEvent.wRepeatCount = 1; + rec.Event.KeyEvent.wVirtualKeyCode = upper; + rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz); + rec.Event.KeyEvent.uChar.AsciiChar = *sz; + rec.Event.KeyEvent.uChar.UnicodeChar = *sz; + rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0; + + WriteConsoleInput( + hStdin, + &rec, + 1, + &dwWritten); + + rec.Event.KeyEvent.bKeyDown = FALSE; + + WriteConsoleInput( + hStdin, + &rec, + 1, + &dwWritten); + + sz++; + } + + return TRUE; +} + + +int CharToCode (char c) +{ + char upper; + + upper = toupper(c); + + switch (c) + { + case 13: + return 28; + + default: + break; + } + + if (isalpha(c)) + return (30 + upper - 65); + + if (isdigit(c)) + return (1 + upper - 47); + + return c; +} + + +BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + COORD coordMax; + + coordMax = GetLargestConsoleWindowSize(hStdout); + + if (cy > coordMax.Y) + cy = coordMax.Y; + + if (cx > coordMax.X) + cx = coordMax.X; + + if (!GetConsoleScreenBufferInfo(hStdout, &info)) + return FALSE; + +// height + info.srWindow.Left = 0; + info.srWindow.Right = info.dwSize.X - 1; + info.srWindow.Top = 0; + info.srWindow.Bottom = cy - 1; + + if (cy < info.dwSize.Y) + { + if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) + return FALSE; + + info.dwSize.Y = cy; + + if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) + return FALSE; + } + else if (cy > info.dwSize.Y) + { + info.dwSize.Y = cy; + + if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) + return FALSE; + + if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) + return FALSE; + } + + if (!GetConsoleScreenBufferInfo(hStdout, &info)) + return FALSE; + +// width + info.srWindow.Left = 0; + info.srWindow.Right = cx - 1; + info.srWindow.Top = 0; + info.srWindow.Bottom = info.dwSize.Y - 1; + + if (cx < info.dwSize.X) + { + if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) + return FALSE; + + info.dwSize.X = cx; + + if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) + return FALSE; + } + else if (cx > info.dwSize.X) + { + info.dwSize.X = cx; + + if (!SetConsoleScreenBufferSize(hStdout, info.dwSize)) + return FALSE; + + if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow)) + return FALSE; + } + + return TRUE; +} + diff --git a/WinQuake/conproc.h b/WinQuake/conproc.h index 743526f..abfe290 100644 --- a/WinQuake/conproc.h +++ b/WinQuake/conproc.h @@ -1,37 +1,37 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// conproc.h - -#define CCOM_WRITE_TEXT 0x2 -// Param1 : Text - -#define CCOM_GET_TEXT 0x3 -// Param1 : Begin line -// Param2 : End line - -#define CCOM_GET_SCR_LINES 0x4 -// No params - -#define CCOM_SET_SCR_LINES 0x5 -// Param1 : Number of lines - -void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild); -void DeinitConProc (void); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// conproc.h + +#define CCOM_WRITE_TEXT 0x2 +// Param1 : Text + +#define CCOM_GET_TEXT 0x3 +// Param1 : Begin line +// Param2 : End line + +#define CCOM_GET_SCR_LINES 0x4 +// No params + +#define CCOM_SET_SCR_LINES 0x5 +// Param1 : Number of lines + +void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild); +void DeinitConProc (void); + diff --git a/WinQuake/console.c b/WinQuake/console.c index cad58f8..345519a 100644 --- a/WinQuake/console.c +++ b/WinQuake/console.c @@ -1,649 +1,649 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// console.c - -#ifdef NeXT -#include -#endif -#ifndef _MSC_VER -#include -#endif -#include -#include "quakedef.h" - -int con_linewidth; - -float con_cursorspeed = 4; - -#define CON_TEXTSIZE 16384 - -qboolean con_forcedup; // because no entities to refresh - -int con_totallines; // total lines in console scrollback -int con_backscroll; // lines up from bottom to display -int con_current; // where next message will be printed -int con_x; // offset in current line for next print -char *con_text=0; - -cvar_t con_notifytime = {"con_notifytime","3"}; //seconds - -#define NUM_CON_TIMES 4 -float con_times[NUM_CON_TIMES]; // realtime time the line was generated - // for transparent notify lines - -int con_vislines; - -qboolean con_debuglog; - -#define MAXCMDLINE 256 -extern char key_lines[32][MAXCMDLINE]; -extern int edit_line; -extern int key_linepos; - - -qboolean con_initialized; - -int con_notifylines; // scan lines to clear for notify lines - -extern void M_Menu_Main_f (void); - -/* -================ -Con_ToggleConsole_f -================ -*/ -void Con_ToggleConsole_f (void) -{ - if (key_dest == key_console) - { - if (cls.state == ca_connected) - { - key_dest = key_game; - key_lines[edit_line][1] = 0; // clear any typing - key_linepos = 1; - } - else - { - M_Menu_Main_f (); - } - } - else - key_dest = key_console; - - SCR_EndLoadingPlaque (); - memset (con_times, 0, sizeof(con_times)); -} - -/* -================ -Con_Clear_f -================ -*/ -void Con_Clear_f (void) -{ - if (con_text) - Q_memset (con_text, ' ', CON_TEXTSIZE); -} - - -/* -================ -Con_ClearNotify -================ -*/ -void Con_ClearNotify (void) -{ - int i; - - for (i=0 ; i> 3) - 2; - - if (width == con_linewidth) - return; - - if (width < 1) // video hasn't been initialized yet - { - width = 38; - con_linewidth = width; - con_totallines = CON_TEXTSIZE / con_linewidth; - Q_memset (con_text, ' ', CON_TEXTSIZE); - } - else - { - oldwidth = con_linewidth; - con_linewidth = width; - oldtotallines = con_totallines; - con_totallines = CON_TEXTSIZE / con_linewidth; - numlines = oldtotallines; - - if (con_totallines < numlines) - numlines = con_totallines; - - numchars = oldwidth; - - if (con_linewidth < numchars) - numchars = con_linewidth; - - Q_memcpy (tbuf, con_text, CON_TEXTSIZE); - Q_memset (con_text, ' ', CON_TEXTSIZE); - - for (i=0 ; i con_linewidth) ) - con_x = 0; - - txt++; - - if (cr) - { - con_current--; - cr = false; - } - - - if (!con_x) - { - Con_Linefeed (); - // mark time for transparent overlay - if (con_current >= 0) - con_times[con_current % NUM_CON_TIMES] = realtime; - } - - switch (c) - { - case '\n': - con_x = 0; - break; - - case '\r': - con_x = 0; - cr = 1; - break; - - default: // display character and advance - y = con_current % con_totallines; - con_text[y*con_linewidth+con_x] = c | mask; - con_x++; - if (con_x >= con_linewidth) - con_x = 0; - break; - } - - } -} - - -/* -================ -Con_DebugLog -================ -*/ -void Con_DebugLog(char *file, char *fmt, ...) -{ - va_list argptr; - static char data[1024]; - int fd; - - va_start(argptr, fmt); - vsprintf(data, fmt, argptr); - va_end(argptr); - fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); - write(fd, data, strlen(data)); - close(fd); -} - - -/* -================ -Con_Printf - -Handles cursor positioning, line wrapping, etc -================ -*/ -#define MAXPRINTMSG 4096 -// FIXME: make a buffer size safe vsprintf? -void Con_Printf (char *fmt, ...) -{ - va_list argptr; - char msg[MAXPRINTMSG]; - static qboolean inupdate; - - va_start (argptr,fmt); - vsprintf (msg,fmt,argptr); - va_end (argptr); - -// also echo to debugging console - Sys_Printf ("%s", msg); // also echo to debugging console - -// log all messages to file - if (con_debuglog) - Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg); - - if (!con_initialized) - return; - - if (cls.state == ca_dedicated) - return; // no graphics mode - -// write it to the scrollable buffer - Con_Print (msg); - -// update the screen if the console is displayed - if (cls.signon != SIGNONS && !scr_disabled_for_loading ) - { - // protect against infinite loop if something in SCR_UpdateScreen calls - // Con_Printd - if (!inupdate) - { - inupdate = true; - SCR_UpdateScreen (); - inupdate = false; - } - } -} - -/* -================ -Con_DPrintf - -A Con_Printf that only shows up if the "developer" cvar is set -================ -*/ -void Con_DPrintf (char *fmt, ...) -{ - va_list argptr; - char msg[MAXPRINTMSG]; - - if (!developer.value) - return; // don't confuse non-developers with techie stuff... - - va_start (argptr,fmt); - vsprintf (msg,fmt,argptr); - va_end (argptr); - - Con_Printf ("%s", msg); -} - - -/* -================== -Con_SafePrintf - -Okay to call even when the screen can't be updated -================== -*/ -void Con_SafePrintf (char *fmt, ...) -{ - va_list argptr; - char msg[1024]; - int temp; - - va_start (argptr,fmt); - vsprintf (msg,fmt,argptr); - va_end (argptr); - - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - Con_Printf ("%s", msg); - scr_disabled_for_loading = temp; -} - - -/* -============================================================================== - -DRAWING - -============================================================================== -*/ - - -/* -================ -Con_DrawInput - -The input line scrolls horizontally if typing goes beyond the right edge -================ -*/ -void Con_DrawInput (void) -{ - int y; - int i; - char *text; - - if (key_dest != key_console && !con_forcedup) - return; // don't draw anything - - text = key_lines[edit_line]; - -// add the cursor frame - text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1); - -// fill out remainder with spaces - for (i=key_linepos+1 ; i< con_linewidth ; i++) - text[i] = ' '; - -// prestep if horizontally scrolling - if (key_linepos >= con_linewidth) - text += 1 + key_linepos - con_linewidth; - -// draw it - y = con_vislines-16; - - for (i=0 ; i con_notifytime.value) - continue; - text = con_text + (i % con_totallines)*con_linewidth; - - clearnotify = 0; - scr_copytop = 1; - - for (x = 0 ; x < con_linewidth ; x++) - Draw_Character ( (x+1)<<3, v, text[x]); - - v += 8; - } - - - if (key_dest == key_message) - { - clearnotify = 0; - scr_copytop = 1; - - x = 0; - - Draw_String (8, v, "say:"); - while(chat_buffer[x]) - { - Draw_Character ( (x+5)<<3, v, chat_buffer[x]); - x++; - } - Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1)); - v += 8; - } - - if (v > con_notifylines) - con_notifylines = v; -} - -/* -================ -Con_DrawConsole - -Draws the console with the solid background -The typing input line at the bottom should only be drawn if typing is allowed -================ -*/ -void Con_DrawConsole (int lines, qboolean drawinput) -{ - int i, x, y; - int rows; - char *text; - int j; - - if (lines <= 0) - return; - -// draw the background - Draw_ConsoleBackground (lines); - -// draw the text - con_vislines = lines; - - rows = (lines-16)>>3; // rows of text to draw - y = lines - 16 - (rows<<3); // may start slightly negative - - for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 ) - { - j = i - con_backscroll; - if (j<0) - j = 0; - text = con_text + (j % con_totallines)*con_linewidth; - - for (x=0 ; x +#endif +#ifndef _MSC_VER +#include +#endif +#include +#include "quakedef.h" + +int con_linewidth; + +float con_cursorspeed = 4; + +#define CON_TEXTSIZE 16384 + +qboolean con_forcedup; // because no entities to refresh + +int con_totallines; // total lines in console scrollback +int con_backscroll; // lines up from bottom to display +int con_current; // where next message will be printed +int con_x; // offset in current line for next print +char *con_text=0; + +cvar_t con_notifytime = {"con_notifytime","3"}; //seconds + +#define NUM_CON_TIMES 4 +float con_times[NUM_CON_TIMES]; // realtime time the line was generated + // for transparent notify lines + +int con_vislines; + +qboolean con_debuglog; + +#define MAXCMDLINE 256 +extern char key_lines[32][MAXCMDLINE]; +extern int edit_line; +extern int key_linepos; + + +qboolean con_initialized; + +int con_notifylines; // scan lines to clear for notify lines + +extern void M_Menu_Main_f (void); + +/* +================ +Con_ToggleConsole_f +================ +*/ +void Con_ToggleConsole_f (void) +{ + if (key_dest == key_console) + { + if (cls.state == ca_connected) + { + key_dest = key_game; + key_lines[edit_line][1] = 0; // clear any typing + key_linepos = 1; + } + else + { + M_Menu_Main_f (); + } + } + else + key_dest = key_console; + + SCR_EndLoadingPlaque (); + memset (con_times, 0, sizeof(con_times)); +} + +/* +================ +Con_Clear_f +================ +*/ +void Con_Clear_f (void) +{ + if (con_text) + Q_memset (con_text, ' ', CON_TEXTSIZE); +} + + +/* +================ +Con_ClearNotify +================ +*/ +void Con_ClearNotify (void) +{ + int i; + + for (i=0 ; i> 3) - 2; + + if (width == con_linewidth) + return; + + if (width < 1) // video hasn't been initialized yet + { + width = 38; + con_linewidth = width; + con_totallines = CON_TEXTSIZE / con_linewidth; + Q_memset (con_text, ' ', CON_TEXTSIZE); + } + else + { + oldwidth = con_linewidth; + con_linewidth = width; + oldtotallines = con_totallines; + con_totallines = CON_TEXTSIZE / con_linewidth; + numlines = oldtotallines; + + if (con_totallines < numlines) + numlines = con_totallines; + + numchars = oldwidth; + + if (con_linewidth < numchars) + numchars = con_linewidth; + + Q_memcpy (tbuf, con_text, CON_TEXTSIZE); + Q_memset (con_text, ' ', CON_TEXTSIZE); + + for (i=0 ; i con_linewidth) ) + con_x = 0; + + txt++; + + if (cr) + { + con_current--; + cr = false; + } + + + if (!con_x) + { + Con_Linefeed (); + // mark time for transparent overlay + if (con_current >= 0) + con_times[con_current % NUM_CON_TIMES] = realtime; + } + + switch (c) + { + case '\n': + con_x = 0; + break; + + case '\r': + con_x = 0; + cr = 1; + break; + + default: // display character and advance + y = con_current % con_totallines; + con_text[y*con_linewidth+con_x] = c | mask; + con_x++; + if (con_x >= con_linewidth) + con_x = 0; + break; + } + + } +} + + +/* +================ +Con_DebugLog +================ +*/ +void Con_DebugLog(char *file, char *fmt, ...) +{ + va_list argptr; + static char data[1024]; + int fd; + + va_start(argptr, fmt); + vsprintf(data, fmt, argptr); + va_end(argptr); + fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); + write(fd, data, strlen(data)); + close(fd); +} + + +/* +================ +Con_Printf + +Handles cursor positioning, line wrapping, etc +================ +*/ +#define MAXPRINTMSG 4096 +// FIXME: make a buffer size safe vsprintf? +void Con_Printf (char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + static qboolean inupdate; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + +// also echo to debugging console + Sys_Printf ("%s", msg); // also echo to debugging console + +// log all messages to file + if (con_debuglog) + Con_DebugLog(va("%s/qconsole.log",com_gamedir), "%s", msg); + + if (!con_initialized) + return; + + if (cls.state == ca_dedicated) + return; // no graphics mode + +// write it to the scrollable buffer + Con_Print (msg); + +// update the screen if the console is displayed + if (cls.signon != SIGNONS && !scr_disabled_for_loading ) + { + // protect against infinite loop if something in SCR_UpdateScreen calls + // Con_Printd + if (!inupdate) + { + inupdate = true; + SCR_UpdateScreen (); + inupdate = false; + } + } +} + +/* +================ +Con_DPrintf + +A Con_Printf that only shows up if the "developer" cvar is set +================ +*/ +void Con_DPrintf (char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + + if (!developer.value) + return; // don't confuse non-developers with techie stuff... + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + Con_Printf ("%s", msg); +} + + +/* +================== +Con_SafePrintf + +Okay to call even when the screen can't be updated +================== +*/ +void Con_SafePrintf (char *fmt, ...) +{ + va_list argptr; + char msg[1024]; + int temp; + + va_start (argptr,fmt); + vsprintf (msg,fmt,argptr); + va_end (argptr); + + temp = scr_disabled_for_loading; + scr_disabled_for_loading = true; + Con_Printf ("%s", msg); + scr_disabled_for_loading = temp; +} + + +/* +============================================================================== + +DRAWING + +============================================================================== +*/ + + +/* +================ +Con_DrawInput + +The input line scrolls horizontally if typing goes beyond the right edge +================ +*/ +void Con_DrawInput (void) +{ + int y; + int i; + char *text; + + if (key_dest != key_console && !con_forcedup) + return; // don't draw anything + + text = key_lines[edit_line]; + +// add the cursor frame + text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1); + +// fill out remainder with spaces + for (i=key_linepos+1 ; i< con_linewidth ; i++) + text[i] = ' '; + +// prestep if horizontally scrolling + if (key_linepos >= con_linewidth) + text += 1 + key_linepos - con_linewidth; + +// draw it + y = con_vislines-16; + + for (i=0 ; i con_notifytime.value) + continue; + text = con_text + (i % con_totallines)*con_linewidth; + + clearnotify = 0; + scr_copytop = 1; + + for (x = 0 ; x < con_linewidth ; x++) + Draw_Character ( (x+1)<<3, v, text[x]); + + v += 8; + } + + + if (key_dest == key_message) + { + clearnotify = 0; + scr_copytop = 1; + + x = 0; + + Draw_String (8, v, "say:"); + while(chat_buffer[x]) + { + Draw_Character ( (x+5)<<3, v, chat_buffer[x]); + x++; + } + Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1)); + v += 8; + } + + if (v > con_notifylines) + con_notifylines = v; +} + +/* +================ +Con_DrawConsole + +Draws the console with the solid background +The typing input line at the bottom should only be drawn if typing is allowed +================ +*/ +void Con_DrawConsole (int lines, qboolean drawinput) +{ + int i, x, y; + int rows; + char *text; + int j; + + if (lines <= 0) + return; + +// draw the background + Draw_ConsoleBackground (lines); + +// draw the text + con_vislines = lines; + + rows = (lines-16)>>3; // rows of text to draw + y = lines - 16 - (rows<<3); // may start slightly negative + + for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 ) + { + j = i - con_backscroll; + if (j<0) + j = 0; + text = con_text + (j % con_totallines)*con_linewidth; + + for (x=0 ; x> 8) ^ data]; -} - -unsigned short CRC_Value(unsigned short crcvalue) -{ - return crcvalue ^ CRC_XOR_VALUE; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/* crc.c */ + +#include "quakedef.h" +#include "crc.h" + +// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 +// and the initial and final xor values shown below... in other words, the +// CCITT standard CRC used by XMODEM + +#define CRC_INIT_VALUE 0xffff +#define CRC_XOR_VALUE 0x0000 + +static unsigned short crctable[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +void CRC_Init(unsigned short *crcvalue) +{ + *crcvalue = CRC_INIT_VALUE; +} + +void CRC_ProcessByte(unsigned short *crcvalue, byte data) +{ + *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; +} + +unsigned short CRC_Value(unsigned short crcvalue) +{ + return crcvalue ^ CRC_XOR_VALUE; } \ No newline at end of file diff --git a/WinQuake/crc.h b/WinQuake/crc.h index cad9772..7cc779c 100644 --- a/WinQuake/crc.h +++ b/WinQuake/crc.h @@ -1,24 +1,24 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -/* crc.h */ - -void CRC_Init(unsigned short *crcvalue); -void CRC_ProcessByte(unsigned short *crcvalue, byte data); -unsigned short CRC_Value(unsigned short crcvalue); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/* crc.h */ + +void CRC_Init(unsigned short *crcvalue); +void CRC_ProcessByte(unsigned short *crcvalue, byte data); +unsigned short CRC_Value(unsigned short crcvalue); diff --git a/WinQuake/cvar.c b/WinQuake/cvar.c index 07a761a..18fb62e 100644 --- a/WinQuake/cvar.c +++ b/WinQuake/cvar.c @@ -1,224 +1,224 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cvar.c -- dynamic variable tracking - -#include "quakedef.h" - -cvar_t *cvar_vars; -char *cvar_null_string = ""; - -/* -============ -Cvar_FindVar -============ -*/ -cvar_t *Cvar_FindVar (char *var_name) -{ - cvar_t *var; - - for (var=cvar_vars ; var ; var=var->next) - if (!Q_strcmp (var_name, var->name)) - return var; - - return NULL; -} - -/* -============ -Cvar_VariableValue -============ -*/ -float Cvar_VariableValue (char *var_name) -{ - cvar_t *var; - - var = Cvar_FindVar (var_name); - if (!var) - return 0; - return Q_atof (var->string); -} - - -/* -============ -Cvar_VariableString -============ -*/ -char *Cvar_VariableString (char *var_name) -{ - cvar_t *var; - - var = Cvar_FindVar (var_name); - if (!var) - return cvar_null_string; - return var->string; -} - - -/* -============ -Cvar_CompleteVariable -============ -*/ -char *Cvar_CompleteVariable (char *partial) -{ - cvar_t *cvar; - int len; - - len = Q_strlen(partial); - - if (!len) - return NULL; - -// check functions - for (cvar=cvar_vars ; cvar ; cvar=cvar->next) - if (!Q_strncmp (partial,cvar->name, len)) - return cvar->name; - - return NULL; -} - - -/* -============ -Cvar_Set -============ -*/ -void Cvar_Set (char *var_name, char *value) -{ - cvar_t *var; - qboolean changed; - - var = Cvar_FindVar (var_name); - if (!var) - { // there is an error in C code if this happens - Con_Printf ("Cvar_Set: variable %s not found\n", var_name); - return; - } - - changed = Q_strcmp(var->string, value); - - Z_Free (var->string); // free the old value string - - var->string = Z_Malloc (Q_strlen(value)+1); - Q_strcpy (var->string, value); - var->value = Q_atof (var->string); - if (var->server && changed) - { - if (sv.active) - SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string); - } -} - -/* -============ -Cvar_SetValue -============ -*/ -void Cvar_SetValue (char *var_name, float value) -{ - char val[32]; - - sprintf (val, "%f",value); - Cvar_Set (var_name, val); -} - - -/* -============ -Cvar_RegisterVariable - -Adds a freestanding variable to the variable list. -============ -*/ -void Cvar_RegisterVariable (cvar_t *variable) -{ - char *oldstr; - -// first check to see if it has allready been defined - if (Cvar_FindVar (variable->name)) - { - Con_Printf ("Can't register variable %s, allready defined\n", variable->name); - return; - } - -// check for overlap with a command - if (Cmd_Exists (variable->name)) - { - Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name); - return; - } - -// copy the value off, because future sets will Z_Free it - oldstr = variable->string; - variable->string = Z_Malloc (Q_strlen(variable->string)+1); - Q_strcpy (variable->string, oldstr); - variable->value = Q_atof (variable->string); - -// link the variable in - variable->next = cvar_vars; - cvar_vars = variable; -} - -/* -============ -Cvar_Command - -Handles variable inspection and changing from the console -============ -*/ -qboolean Cvar_Command (void) -{ - cvar_t *v; - -// check variables - v = Cvar_FindVar (Cmd_Argv(0)); - if (!v) - return false; - -// perform a variable print or set - if (Cmd_Argc() == 1) - { - Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string); - return true; - } - - Cvar_Set (v->name, Cmd_Argv(1)); - return true; -} - - -/* -============ -Cvar_WriteVariables - -Writes lines containing "set variable value" for all variables -with the archive flag set to true. -============ -*/ -void Cvar_WriteVariables (FILE *f) -{ - cvar_t *var; - - for (var = cvar_vars ; var ; var = var->next) - if (var->archive) - fprintf (f, "%s \"%s\"\n", var->name, var->string); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cvar.c -- dynamic variable tracking + +#include "quakedef.h" + +cvar_t *cvar_vars; +char *cvar_null_string = ""; + +/* +============ +Cvar_FindVar +============ +*/ +cvar_t *Cvar_FindVar (char *var_name) +{ + cvar_t *var; + + for (var=cvar_vars ; var ; var=var->next) + if (!Q_strcmp (var_name, var->name)) + return var; + + return NULL; +} + +/* +============ +Cvar_VariableValue +============ +*/ +float Cvar_VariableValue (char *var_name) +{ + cvar_t *var; + + var = Cvar_FindVar (var_name); + if (!var) + return 0; + return Q_atof (var->string); +} + + +/* +============ +Cvar_VariableString +============ +*/ +char *Cvar_VariableString (char *var_name) +{ + cvar_t *var; + + var = Cvar_FindVar (var_name); + if (!var) + return cvar_null_string; + return var->string; +} + + +/* +============ +Cvar_CompleteVariable +============ +*/ +char *Cvar_CompleteVariable (char *partial) +{ + cvar_t *cvar; + int len; + + len = Q_strlen(partial); + + if (!len) + return NULL; + +// check functions + for (cvar=cvar_vars ; cvar ; cvar=cvar->next) + if (!Q_strncmp (partial,cvar->name, len)) + return cvar->name; + + return NULL; +} + + +/* +============ +Cvar_Set +============ +*/ +void Cvar_Set (char *var_name, char *value) +{ + cvar_t *var; + qboolean changed; + + var = Cvar_FindVar (var_name); + if (!var) + { // there is an error in C code if this happens + Con_Printf ("Cvar_Set: variable %s not found\n", var_name); + return; + } + + changed = Q_strcmp(var->string, value); + + Z_Free (var->string); // free the old value string + + var->string = Z_Malloc (Q_strlen(value)+1); + Q_strcpy (var->string, value); + var->value = Q_atof (var->string); + if (var->server && changed) + { + if (sv.active) + SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string); + } +} + +/* +============ +Cvar_SetValue +============ +*/ +void Cvar_SetValue (char *var_name, float value) +{ + char val[32]; + + sprintf (val, "%f",value); + Cvar_Set (var_name, val); +} + + +/* +============ +Cvar_RegisterVariable + +Adds a freestanding variable to the variable list. +============ +*/ +void Cvar_RegisterVariable (cvar_t *variable) +{ + char *oldstr; + +// first check to see if it has allready been defined + if (Cvar_FindVar (variable->name)) + { + Con_Printf ("Can't register variable %s, allready defined\n", variable->name); + return; + } + +// check for overlap with a command + if (Cmd_Exists (variable->name)) + { + Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name); + return; + } + +// copy the value off, because future sets will Z_Free it + oldstr = variable->string; + variable->string = Z_Malloc (Q_strlen(variable->string)+1); + Q_strcpy (variable->string, oldstr); + variable->value = Q_atof (variable->string); + +// link the variable in + variable->next = cvar_vars; + cvar_vars = variable; +} + +/* +============ +Cvar_Command + +Handles variable inspection and changing from the console +============ +*/ +qboolean Cvar_Command (void) +{ + cvar_t *v; + +// check variables + v = Cvar_FindVar (Cmd_Argv(0)); + if (!v) + return false; + +// perform a variable print or set + if (Cmd_Argc() == 1) + { + Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string); + return true; + } + + Cvar_Set (v->name, Cmd_Argv(1)); + return true; +} + + +/* +============ +Cvar_WriteVariables + +Writes lines containing "set variable value" for all variables +with the archive flag set to true. +============ +*/ +void Cvar_WriteVariables (FILE *f) +{ + cvar_t *var; + + for (var = cvar_vars ; var ; var = var->next) + if (var->archive) + fprintf (f, "%s \"%s\"\n", var->name, var->string); +} + diff --git a/WinQuake/cvar.h b/WinQuake/cvar.h index 009b747..771b340 100644 --- a/WinQuake/cvar.h +++ b/WinQuake/cvar.h @@ -1,97 +1,97 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// cvar.h - -/* - -cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly -in C code. - -it is sufficient to initialize a cvar_t with just the first two fields, or -you can add a ,true flag for variables that you want saved to the configuration -file when the game is quit: - -cvar_t r_draworder = {"r_draworder","1"}; -cvar_t scr_screensize = {"screensize","1",true}; - -Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed: -Cvar_RegisterVariable (&host_framerate); - - -C code usually just references a cvar in place: -if ( r_draworder.value ) - -It could optionally ask for the value to be looked up for a string name: -if (Cvar_VariableValue ("r_draworder")) - -Interpreted prog code can access cvars with the cvar(name) or -cvar_set (name, value) internal functions: -teamplay = cvar("teamplay"); -cvar_set ("registered", "1"); - -The user can access cvars from the console in two ways: -r_draworder prints the current value -r_draworder 0 sets the current value to 0 -Cvars are restricted from having the same names as commands to keep this -interface from being ambiguous. -*/ - -typedef struct cvar_s -{ - char *name; - char *string; - qboolean archive; // set to true to cause it to be saved to vars.rc - qboolean server; // notifies players when changed - float value; - struct cvar_s *next; -} cvar_t; - -void Cvar_RegisterVariable (cvar_t *variable); -// registers a cvar that allready has the name, string, and optionally the -// archive elements set. - -void Cvar_Set (char *var_name, char *value); -// equivelant to " " typed at the console - -void Cvar_SetValue (char *var_name, float value); -// expands value to a string and calls Cvar_Set - -float Cvar_VariableValue (char *var_name); -// returns 0 if not defined or non numeric - -char *Cvar_VariableString (char *var_name); -// returns an empty string if not defined - -char *Cvar_CompleteVariable (char *partial); -// attempts to match a partial variable name for command line completion -// returns NULL if nothing fits - -qboolean Cvar_Command (void); -// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known -// command. Returns true if the command was a variable reference that -// was handled. (print or change) - -void Cvar_WriteVariables (FILE *f); -// Writes lines containing "set variable value" for all variables -// with the archive flag set to true. - -cvar_t *Cvar_FindVar (char *var_name); - -extern cvar_t *cvar_vars; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// cvar.h + +/* + +cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly +in C code. + +it is sufficient to initialize a cvar_t with just the first two fields, or +you can add a ,true flag for variables that you want saved to the configuration +file when the game is quit: + +cvar_t r_draworder = {"r_draworder","1"}; +cvar_t scr_screensize = {"screensize","1",true}; + +Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed: +Cvar_RegisterVariable (&host_framerate); + + +C code usually just references a cvar in place: +if ( r_draworder.value ) + +It could optionally ask for the value to be looked up for a string name: +if (Cvar_VariableValue ("r_draworder")) + +Interpreted prog code can access cvars with the cvar(name) or +cvar_set (name, value) internal functions: +teamplay = cvar("teamplay"); +cvar_set ("registered", "1"); + +The user can access cvars from the console in two ways: +r_draworder prints the current value +r_draworder 0 sets the current value to 0 +Cvars are restricted from having the same names as commands to keep this +interface from being ambiguous. +*/ + +typedef struct cvar_s +{ + char *name; + char *string; + qboolean archive; // set to true to cause it to be saved to vars.rc + qboolean server; // notifies players when changed + float value; + struct cvar_s *next; +} cvar_t; + +void Cvar_RegisterVariable (cvar_t *variable); +// registers a cvar that allready has the name, string, and optionally the +// archive elements set. + +void Cvar_Set (char *var_name, char *value); +// equivelant to " " typed at the console + +void Cvar_SetValue (char *var_name, float value); +// expands value to a string and calls Cvar_Set + +float Cvar_VariableValue (char *var_name); +// returns 0 if not defined or non numeric + +char *Cvar_VariableString (char *var_name); +// returns an empty string if not defined + +char *Cvar_CompleteVariable (char *partial); +// attempts to match a partial variable name for command line completion +// returns NULL if nothing fits + +qboolean Cvar_Command (void); +// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known +// command. Returns true if the command was a variable reference that +// was handled. (print or change) + +void Cvar_WriteVariables (FILE *f); +// Writes lines containing "set variable value" for all variables +// with the archive flag set to true. + +cvar_t *Cvar_FindVar (char *var_name); + +extern cvar_t *cvar_vars; diff --git a/WinQuake/d_draw.s b/WinQuake/d_draw.s index f0a6e2a..d50b982 100644 --- a/WinQuake/d_draw.s +++ b/WinQuake/d_draw.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_draw.s // x86 assembly-language horizontal 8-bpp span-drawing code. diff --git a/WinQuake/d_draw16.s b/WinQuake/d_draw16.s index cccfdbf..4cd0a17 100644 --- a/WinQuake/d_draw16.s +++ b/WinQuake/d_draw16.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_draw16.s // x86 assembly-language horizontal 8-bpp span-drawing code, with 16-pixel diff --git a/WinQuake/d_edge.c b/WinQuake/d_edge.c index 52cc8eb..bbd1c2c 100644 --- a/WinQuake/d_edge.c +++ b/WinQuake/d_edge.c @@ -1,331 +1,331 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_edge.c - -#include "quakedef.h" -#include "d_local.h" - -static int miplevel; - -float scale_for_mip; -int screenwidth; -int ubasestep, errorterm, erroradjustup, erroradjustdown; -int vstartscan; - -// FIXME: should go away -extern void R_RotateBmodel (void); -extern void R_TransformFrustum (void); - -vec3_t transformed_modelorg; - -/* -============== -D_DrawPoly - -============== -*/ -void D_DrawPoly (void) -{ -// this driver takes spans, not polygons -} - - -/* -============= -D_MipLevelForScale -============= -*/ -int D_MipLevelForScale (float scale) -{ - int lmiplevel; - - if (scale >= d_scalemip[0] ) - lmiplevel = 0; - else if (scale >= d_scalemip[1] ) - lmiplevel = 1; - else if (scale >= d_scalemip[2] ) - lmiplevel = 2; - else - lmiplevel = 3; - - if (lmiplevel < d_minmip) - lmiplevel = d_minmip; - - return lmiplevel; -} - - -/* -============== -D_DrawSolidSurface -============== -*/ - -// FIXME: clean this up - -void D_DrawSolidSurface (surf_t *surf, int color) -{ - espan_t *span; - byte *pdest; - int u, u2, pix; - - pix = (color<<24) | (color<<16) | (color<<8) | color; - for (span=surf->spans ; span ; span=span->pnext) - { - pdest = (byte *)d_viewbuffer + screenwidth*span->v; - u = span->u; - u2 = span->u + span->count - 1; - ((byte *)pdest)[u] = pix; - - if (u2 - u < 8) - { - for (u++ ; u <= u2 ; u++) - ((byte *)pdest)[u] = pix; - } - else - { - for (u++ ; u & 3 ; u++) - ((byte *)pdest)[u] = pix; - - u2 -= 4; - for ( ; u <= u2 ; u+=4) - *(int *)((byte *)pdest + u) = pix; - u2 += 4; - for ( ; u <= u2 ; u++) - ((byte *)pdest)[u] = pix; - } - } -} - - -/* -============== -D_CalcGradients -============== -*/ -void D_CalcGradients (msurface_t *pface) -{ - mplane_t *pplane; - float mipscale; - vec3_t p_temp1; - vec3_t p_saxis, p_taxis; - float t; - - pplane = pface->plane; - - mipscale = 1.0 / (float)(1 << miplevel); - - TransformVector (pface->texinfo->vecs[0], p_saxis); - TransformVector (pface->texinfo->vecs[1], p_taxis); - - t = xscaleinv * mipscale; - d_sdivzstepu = p_saxis[0] * t; - d_tdivzstepu = p_taxis[0] * t; - - t = yscaleinv * mipscale; - d_sdivzstepv = -p_saxis[1] * t; - d_tdivzstepv = -p_taxis[1] * t; - - d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - - ycenter * d_sdivzstepv; - d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - - ycenter * d_tdivzstepv; - - VectorScale (transformed_modelorg, mipscale, p_temp1); - - t = 0x10000*mipscale; - sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - - ((pface->texturemins[0] << 16) >> miplevel) - + pface->texinfo->vecs[0][3]*t; - tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - - ((pface->texturemins[1] << 16) >> miplevel) - + pface->texinfo->vecs[1][3]*t; - -// -// -1 (-epsilon) so we never wander off the edge of the texture -// - bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; - bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; -} - - -/* -============== -D_DrawSurfaces -============== -*/ -void D_DrawSurfaces (void) -{ - surf_t *s; - msurface_t *pface; - surfcache_t *pcurrentcache; - vec3_t world_transformed_modelorg; - vec3_t local_modelorg; - - currententity = &cl_entities[0]; - TransformVector (modelorg, transformed_modelorg); - VectorCopy (transformed_modelorg, world_transformed_modelorg); - -// TODO: could preset a lot of this at mode set time - if (r_drawflat.value) - { - for (s = &surfaces[1] ; sspans) - continue; - - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - - D_DrawSolidSurface (s, (int)s->data & 0xFF); - D_DrawZSpans (s->spans); - } - } - else - { - for (s = &surfaces[1] ; sspans) - continue; - - r_drawnpolycount++; - - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - - if (s->flags & SURF_DRAWSKY) - { - if (!r_skymade) - { - R_MakeSky (); - } - - D_DrawSkyScans8 (s->spans); - D_DrawZSpans (s->spans); - } - else if (s->flags & SURF_DRAWBACKGROUND) - { - // set up a gradient for the background surface that places it - // effectively at infinity distance from the viewpoint - d_zistepu = 0; - d_zistepv = 0; - d_ziorigin = -0.9; - - D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF); - D_DrawZSpans (s->spans); - } - else if (s->flags & SURF_DRAWTURB) - { - pface = s->data; - miplevel = 0; - cacheblock = (pixel_t *) - ((byte *)pface->texinfo->texture + - pface->texinfo->texture->offsets[0]); - cachewidth = 64; - - if (s->insubmodel) - { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - currententity = s->entity; //FIXME: make this passed in to - // R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, - local_modelorg); - TransformVector (local_modelorg, transformed_modelorg); - - R_RotateBmodel (); // FIXME: don't mess with the frustum, - // make entity passed in - } - - D_CalcGradients (pface); - Turbulent8 (s->spans); - D_DrawZSpans (s->spans); - - if (s->insubmodel) - { - // - // restore the old drawing state - // FIXME: we don't want to do this every time! - // TODO: speed up - // - currententity = &cl_entities[0]; - VectorCopy (world_transformed_modelorg, - transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - R_TransformFrustum (); - } - } - else - { - if (s->insubmodel) - { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - currententity = s->entity; //FIXME: make this passed in to - // R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, local_modelorg); - TransformVector (local_modelorg, transformed_modelorg); - - R_RotateBmodel (); // FIXME: don't mess with the frustum, - // make entity passed in - } - - pface = s->data; - miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip - * pface->texinfo->mipadjust); - - // FIXME: make this passed in to D_CacheSurface - pcurrentcache = D_CacheSurface (pface, miplevel); - - cacheblock = (pixel_t *)pcurrentcache->data; - cachewidth = pcurrentcache->width; - - D_CalcGradients (pface); - - (*d_drawspans) (s->spans); - - D_DrawZSpans (s->spans); - - if (s->insubmodel) - { - // - // restore the old drawing state - // FIXME: we don't want to do this every time! - // TODO: speed up - // - currententity = &cl_entities[0]; - VectorCopy (world_transformed_modelorg, - transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - R_TransformFrustum (); - } - } - } - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_edge.c + +#include "quakedef.h" +#include "d_local.h" + +static int miplevel; + +float scale_for_mip; +int screenwidth; +int ubasestep, errorterm, erroradjustup, erroradjustdown; +int vstartscan; + +// FIXME: should go away +extern void R_RotateBmodel (void); +extern void R_TransformFrustum (void); + +vec3_t transformed_modelorg; + +/* +============== +D_DrawPoly + +============== +*/ +void D_DrawPoly (void) +{ +// this driver takes spans, not polygons +} + + +/* +============= +D_MipLevelForScale +============= +*/ +int D_MipLevelForScale (float scale) +{ + int lmiplevel; + + if (scale >= d_scalemip[0] ) + lmiplevel = 0; + else if (scale >= d_scalemip[1] ) + lmiplevel = 1; + else if (scale >= d_scalemip[2] ) + lmiplevel = 2; + else + lmiplevel = 3; + + if (lmiplevel < d_minmip) + lmiplevel = d_minmip; + + return lmiplevel; +} + + +/* +============== +D_DrawSolidSurface +============== +*/ + +// FIXME: clean this up + +void D_DrawSolidSurface (surf_t *surf, int color) +{ + espan_t *span; + byte *pdest; + int u, u2, pix; + + pix = (color<<24) | (color<<16) | (color<<8) | color; + for (span=surf->spans ; span ; span=span->pnext) + { + pdest = (byte *)d_viewbuffer + screenwidth*span->v; + u = span->u; + u2 = span->u + span->count - 1; + ((byte *)pdest)[u] = pix; + + if (u2 - u < 8) + { + for (u++ ; u <= u2 ; u++) + ((byte *)pdest)[u] = pix; + } + else + { + for (u++ ; u & 3 ; u++) + ((byte *)pdest)[u] = pix; + + u2 -= 4; + for ( ; u <= u2 ; u+=4) + *(int *)((byte *)pdest + u) = pix; + u2 += 4; + for ( ; u <= u2 ; u++) + ((byte *)pdest)[u] = pix; + } + } +} + + +/* +============== +D_CalcGradients +============== +*/ +void D_CalcGradients (msurface_t *pface) +{ + mplane_t *pplane; + float mipscale; + vec3_t p_temp1; + vec3_t p_saxis, p_taxis; + float t; + + pplane = pface->plane; + + mipscale = 1.0 / (float)(1 << miplevel); + + TransformVector (pface->texinfo->vecs[0], p_saxis); + TransformVector (pface->texinfo->vecs[1], p_taxis); + + t = xscaleinv * mipscale; + d_sdivzstepu = p_saxis[0] * t; + d_tdivzstepu = p_taxis[0] * t; + + t = yscaleinv * mipscale; + d_sdivzstepv = -p_saxis[1] * t; + d_tdivzstepv = -p_taxis[1] * t; + + d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - + ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - + ycenter * d_tdivzstepv; + + VectorScale (transformed_modelorg, mipscale, p_temp1); + + t = 0x10000*mipscale; + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + ((pface->texturemins[0] << 16) >> miplevel) + + pface->texinfo->vecs[0][3]*t; + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + ((pface->texturemins[1] << 16) >> miplevel) + + pface->texinfo->vecs[1][3]*t; + +// +// -1 (-epsilon) so we never wander off the edge of the texture +// + bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; + bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; +} + + +/* +============== +D_DrawSurfaces +============== +*/ +void D_DrawSurfaces (void) +{ + surf_t *s; + msurface_t *pface; + surfcache_t *pcurrentcache; + vec3_t world_transformed_modelorg; + vec3_t local_modelorg; + + currententity = &cl_entities[0]; + TransformVector (modelorg, transformed_modelorg); + VectorCopy (transformed_modelorg, world_transformed_modelorg); + +// TODO: could preset a lot of this at mode set time + if (r_drawflat.value) + { + for (s = &surfaces[1] ; sspans) + continue; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + D_DrawSolidSurface (s, (int)s->data & 0xFF); + D_DrawZSpans (s->spans); + } + } + else + { + for (s = &surfaces[1] ; sspans) + continue; + + r_drawnpolycount++; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + if (s->flags & SURF_DRAWSKY) + { + if (!r_skymade) + { + R_MakeSky (); + } + + D_DrawSkyScans8 (s->spans); + D_DrawZSpans (s->spans); + } + else if (s->flags & SURF_DRAWBACKGROUND) + { + // set up a gradient for the background surface that places it + // effectively at infinity distance from the viewpoint + d_zistepu = 0; + d_zistepv = 0; + d_ziorigin = -0.9; + + D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF); + D_DrawZSpans (s->spans); + } + else if (s->flags & SURF_DRAWTURB) + { + pface = s->data; + miplevel = 0; + cacheblock = (pixel_t *) + ((byte *)pface->texinfo->texture + + pface->texinfo->texture->offsets[0]); + cachewidth = 64; + + if (s->insubmodel) + { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + currententity = s->entity; //FIXME: make this passed in to + // R_RotateBmodel () + VectorSubtract (r_origin, currententity->origin, + local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the frustum, + // make entity passed in + } + + D_CalcGradients (pface); + Turbulent8 (s->spans); + D_DrawZSpans (s->spans); + + if (s->insubmodel) + { + // + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + // + currententity = &cl_entities[0]; + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + R_TransformFrustum (); + } + } + else + { + if (s->insubmodel) + { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + currententity = s->entity; //FIXME: make this passed in to + // R_RotateBmodel () + VectorSubtract (r_origin, currententity->origin, local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the frustum, + // make entity passed in + } + + pface = s->data; + miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip + * pface->texinfo->mipadjust); + + // FIXME: make this passed in to D_CacheSurface + pcurrentcache = D_CacheSurface (pface, miplevel); + + cacheblock = (pixel_t *)pcurrentcache->data; + cachewidth = pcurrentcache->width; + + D_CalcGradients (pface); + + (*d_drawspans) (s->spans); + + D_DrawZSpans (s->spans); + + if (s->insubmodel) + { + // + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + // + currententity = &cl_entities[0]; + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + R_TransformFrustum (); + } + } + } + } +} + diff --git a/WinQuake/d_fill.c b/WinQuake/d_fill.c index e6c1473..b1ebb5f 100644 --- a/WinQuake/d_fill.c +++ b/WinQuake/d_fill.c @@ -1,88 +1,88 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_clear: clears a specified rectangle to the specified color - -#include "quakedef.h" - - -/* -================ -D_FillRect -================ -*/ -void D_FillRect (vrect_t *rect, int color) -{ - int rx, ry, rwidth, rheight; - unsigned char *dest; - unsigned *ldest; - - rx = rect->x; - ry = rect->y; - rwidth = rect->width; - rheight = rect->height; - - if (rx < 0) - { - rwidth += rx; - rx = 0; - } - if (ry < 0) - { - rheight += ry; - ry = 0; - } - if (rx+rwidth > vid.width) - rwidth = vid.width - rx; - if (ry+rheight > vid.height) - rheight = vid.height - rx; - - if (rwidth < 1 || rheight < 1) - return; - - dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx); - - if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0)) - { - // faster aligned dword clear - ldest = (unsigned *)dest; - color += color << 16; - - rwidth >>= 2; - color += color << 8; - - for (ry=0 ; ryx; + ry = rect->y; + rwidth = rect->width; + rheight = rect->height; + + if (rx < 0) + { + rwidth += rx; + rx = 0; + } + if (ry < 0) + { + rheight += ry; + ry = 0; + } + if (rx+rwidth > vid.width) + rwidth = vid.width - rx; + if (ry+rheight > vid.height) + rheight = vid.height - rx; + + if (rwidth < 1 || rheight < 1) + return; + + dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx); + + if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0)) + { + // faster aligned dword clear + ldest = (unsigned *)dest; + color += color << 16; + + rwidth >>= 2; + color += color << 8; + + for (ry=0 ; ry 3) - d_minmip = 3; - else if (d_minmip < 0) - d_minmip = 0; - - for (i=0 ; i<(NUM_MIPS-1) ; i++) - d_scalemip[i] = basemip[i] * d_mipscale.value; - -#if id386 - if (d_subdiv16.value) - d_drawspans = D_DrawSpans16; - else - d_drawspans = D_DrawSpans8; -#else - d_drawspans = D_DrawSpans8; -#endif - - d_aflatcolor = 0; -} - - -/* -=============== -D_UpdateRects -=============== -*/ -void D_UpdateRects (vrect_t *prect) -{ - -// the software driver draws these directly to the vid buffer - - UNUSED(prect); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_init.c: rasterization driver initialization + +#include "quakedef.h" +#include "d_local.h" + +#define NUM_MIPS 4 + +cvar_t d_subdiv16 = {"d_subdiv16", "1"}; +cvar_t d_mipcap = {"d_mipcap", "0"}; +cvar_t d_mipscale = {"d_mipscale", "1"}; + +surfcache_t *d_initial_rover; +qboolean d_roverwrapped; +int d_minmip; +float d_scalemip[NUM_MIPS-1]; + +static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8}; + +extern int d_aflatcolor; + +void (*d_drawspans) (espan_t *pspan); + + +/* +=============== +D_Init +=============== +*/ +void D_Init (void) +{ + + r_skydirect = 1; + + Cvar_RegisterVariable (&d_subdiv16); + Cvar_RegisterVariable (&d_mipcap); + Cvar_RegisterVariable (&d_mipscale); + + r_drawpolys = false; + r_worldpolysbacktofront = false; + r_recursiveaffinetriangles = true; + r_pixbytes = 1; + r_aliasuvscale = 1.0; +} + + +/* +=============== +D_CopyRects +=============== +*/ +void D_CopyRects (vrect_t *prects, int transparent) +{ + +// this function is only required if the CPU doesn't have direct access to the +// back buffer, and there's some driver interface function that the driver +// doesn't support and requires Quake to do in software (such as drawing the +// console); Quake will then draw into wherever the driver points vid.buffer +// and will call this function before swapping buffers + + UNUSED(prects); + UNUSED(transparent); +} + + +/* +=============== +D_EnableBackBufferAccess +=============== +*/ +void D_EnableBackBufferAccess (void) +{ + VID_LockBuffer (); +} + + +/* +=============== +D_TurnZOn +=============== +*/ +void D_TurnZOn (void) +{ +// not needed for software version +} + + +/* +=============== +D_DisableBackBufferAccess +=============== +*/ +void D_DisableBackBufferAccess (void) +{ + VID_UnlockBuffer (); +} + + +/* +=============== +D_SetupFrame +=============== +*/ +void D_SetupFrame (void) +{ + int i; + + if (r_dowarp) + d_viewbuffer = r_warpbuffer; + else + d_viewbuffer = (void *)(byte *)vid.buffer; + + if (r_dowarp) + screenwidth = WARP_WIDTH; + else + screenwidth = vid.rowbytes; + + d_roverwrapped = false; + d_initial_rover = sc_rover; + + d_minmip = d_mipcap.value; + if (d_minmip > 3) + d_minmip = 3; + else if (d_minmip < 0) + d_minmip = 0; + + for (i=0 ; i<(NUM_MIPS-1) ; i++) + d_scalemip[i] = basemip[i] * d_mipscale.value; + +#if id386 + if (d_subdiv16.value) + d_drawspans = D_DrawSpans16; + else + d_drawspans = D_DrawSpans8; +#else + d_drawspans = D_DrawSpans8; +#endif + + d_aflatcolor = 0; +} + + +/* +=============== +D_UpdateRects +=============== +*/ +void D_UpdateRects (vrect_t *prect) +{ + +// the software driver draws these directly to the vid buffer + + UNUSED(prect); +} + diff --git a/WinQuake/d_local.h b/WinQuake/d_local.h index af92489..4636c45 100644 --- a/WinQuake/d_local.h +++ b/WinQuake/d_local.h @@ -1,111 +1,111 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_local.h: private rasterization driver defs - -#include "r_shared.h" - -// -// TODO: fine-tune this; it's based on providing some overage even if there -// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each -// -#define SCANBUFFERPAD 0x1000 - -#define R_SKY_SMASK 0x007F0000 -#define R_SKY_TMASK 0x007F0000 - -#define DS_SPAN_LIST_END -128 - -#define SURFCACHE_SIZE_AT_320X200 600*1024 - -typedef struct surfcache_s -{ - struct surfcache_s *next; - struct surfcache_s **owner; // NULL is an empty chunk of memory - int lightadj[MAXLIGHTMAPS]; // checked for strobe flush - int dlight; - int size; // including header - unsigned width; - unsigned height; // DEBUG only needed for debug - float mipscale; - struct texture_s *texture; // checked for animating textures - byte data[4]; // width*height elements -} surfcache_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct sspan_s -{ - int u, v, count; -} sspan_t; - -extern cvar_t d_subdiv16; - -extern float scale_for_mip; - -extern qboolean d_roverwrapped; -extern surfcache_t *sc_rover; -extern surfcache_t *d_initial_rover; - -extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; -extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; -extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; - -fixed16_t sadjust, tadjust; -fixed16_t bbextents, bbextentt; - - -void D_DrawSpans8 (espan_t *pspans); -void D_DrawSpans16 (espan_t *pspans); -void D_DrawZSpans (espan_t *pspans); -void Turbulent8 (espan_t *pspan); -void D_SpriteDrawSpans (sspan_t *pspan); - -void D_DrawSkyScans8 (espan_t *pspan); -void D_DrawSkyScans16 (espan_t *pspan); - -void R_ShowSubDiv (void); -void (*prealspandrawer)(void); -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); - -extern int D_MipLevelForScale (float scale); - -#if id386 -extern void D_PolysetAff8Start (void); -extern void D_PolysetAff8End (void); -#endif - -extern short *d_pzbuffer; -extern unsigned int d_zrowbytes, d_zwidth; - -extern int *d_pscantable; -extern int d_scantable[MAXHEIGHT]; - -extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; - -extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; - -extern pixel_t *d_viewbuffer; - -extern short *zspantable[MAXHEIGHT]; - -extern int d_minmip; -extern float d_scalemip[3]; - -extern void (*d_drawspans) (espan_t *pspan); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_local.h: private rasterization driver defs + +#include "r_shared.h" + +// +// TODO: fine-tune this; it's based on providing some overage even if there +// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each +// +#define SCANBUFFERPAD 0x1000 + +#define R_SKY_SMASK 0x007F0000 +#define R_SKY_TMASK 0x007F0000 + +#define DS_SPAN_LIST_END -128 + +#define SURFCACHE_SIZE_AT_320X200 600*1024 + +typedef struct surfcache_s +{ + struct surfcache_s *next; + struct surfcache_s **owner; // NULL is an empty chunk of memory + int lightadj[MAXLIGHTMAPS]; // checked for strobe flush + int dlight; + int size; // including header + unsigned width; + unsigned height; // DEBUG only needed for debug + float mipscale; + struct texture_s *texture; // checked for animating textures + byte data[4]; // width*height elements +} surfcache_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct sspan_s +{ + int u, v, count; +} sspan_t; + +extern cvar_t d_subdiv16; + +extern float scale_for_mip; + +extern qboolean d_roverwrapped; +extern surfcache_t *sc_rover; +extern surfcache_t *d_initial_rover; + +extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; +extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; +extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; + +fixed16_t sadjust, tadjust; +fixed16_t bbextents, bbextentt; + + +void D_DrawSpans8 (espan_t *pspans); +void D_DrawSpans16 (espan_t *pspans); +void D_DrawZSpans (espan_t *pspans); +void Turbulent8 (espan_t *pspan); +void D_SpriteDrawSpans (sspan_t *pspan); + +void D_DrawSkyScans8 (espan_t *pspan); +void D_DrawSkyScans16 (espan_t *pspan); + +void R_ShowSubDiv (void); +void (*prealspandrawer)(void); +surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); + +extern int D_MipLevelForScale (float scale); + +#if id386 +extern void D_PolysetAff8Start (void); +extern void D_PolysetAff8End (void); +#endif + +extern short *d_pzbuffer; +extern unsigned int d_zrowbytes, d_zwidth; + +extern int *d_pscantable; +extern int d_scantable[MAXHEIGHT]; + +extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; + +extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; + +extern pixel_t *d_viewbuffer; + +extern short *zspantable[MAXHEIGHT]; + +extern int d_minmip; +extern float d_scalemip[3]; + +extern void (*d_drawspans) (espan_t *pspan); + diff --git a/WinQuake/d_modech.c b/WinQuake/d_modech.c index 75c188e..f1162b4 100644 --- a/WinQuake/d_modech.c +++ b/WinQuake/d_modech.c @@ -1,107 +1,107 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_modech.c: called when mode has just changed - -#include "quakedef.h" -#include "d_local.h" - -int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; - -int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; - -int d_scantable[MAXHEIGHT]; -short *zspantable[MAXHEIGHT]; - -/* -================ -D_Patch -================ -*/ -void D_Patch (void) -{ -#if id386 - - static qboolean protectset8 = false; - - if (!protectset8) - { - Sys_MakeCodeWriteable ((int)D_PolysetAff8Start, - (int)D_PolysetAff8End - (int)D_PolysetAff8Start); - protectset8 = true; - } - -#endif // id386 -} - - -/* -================ -D_ViewChanged -================ -*/ -void D_ViewChanged (void) -{ - int rowbytes; - - if (r_dowarp) - rowbytes = WARP_WIDTH; - else - rowbytes = vid.rowbytes; - - scale_for_mip = xscale; - if (yscale > xscale) - scale_for_mip = yscale; - - d_zrowbytes = vid.width * 2; - d_zwidth = vid.width; - - d_pix_min = r_refdef.vrect.width / 320; - if (d_pix_min < 1) - d_pix_min = 1; - - d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5); - d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5); - if (d_pix_max < 1) - d_pix_max = 1; - - if (pixelAspect > 1.4) - d_y_aspect_shift = 1; - else - d_y_aspect_shift = 0; - - d_vrectx = r_refdef.vrect.x; - d_vrecty = r_refdef.vrect.y; - d_vrectright_particle = r_refdef.vrectright - d_pix_max; - d_vrectbottom_particle = - r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); - - { - int i; - - for (i=0 ; i xscale) + scale_for_mip = yscale; + + d_zrowbytes = vid.width * 2; + d_zwidth = vid.width; + + d_pix_min = r_refdef.vrect.width / 320; + if (d_pix_min < 1) + d_pix_min = 1; + + d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5); + d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5); + if (d_pix_max < 1) + d_pix_max = 1; + + if (pixelAspect > 1.4) + d_y_aspect_shift = 1; + else + d_y_aspect_shift = 0; + + d_vrectx = r_refdef.vrect.x; + d_vrecty = r_refdef.vrect.y; + d_vrectright_particle = r_refdef.vrectright - d_pix_max; + d_vrectbottom_particle = + r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); + + { + int i; + + for (i=0 ; iorg, r_origin, local); - - transformed[0] = DotProduct(local, r_pright); - transformed[1] = DotProduct(local, r_pup); - transformed[2] = DotProduct(local, r_ppn); - - if (transformed[2] < PARTICLE_Z_CLIP) - return; - -// project the point -// FIXME: preadjust xcenter and ycenter - zi = 1.0 / transformed[2]; - u = (int)(xcenter + zi * transformed[0] + 0.5); - v = (int)(ycenter - zi * transformed[1] + 0.5); - - if ((v > d_vrectbottom_particle) || - (u > d_vrectright_particle) || - (v < d_vrecty) || - (u < d_vrectx)) - { - return; - } - - pz = d_pzbuffer + (d_zwidth * v) + u; - pdest = d_viewbuffer + d_scantable[v] + u; - izi = (int)(zi * 0x8000); - - pix = izi >> d_pix_shift; - - if (pix < d_pix_min) - pix = d_pix_min; - else if (pix > d_pix_max) - pix = d_pix_max; - - switch (pix) - { - case 1: - count = 1 << d_y_aspect_shift; - - for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) - { - if (pz[0] <= izi) - { - pz[0] = izi; - pdest[0] = pparticle->color; - } - } - break; - - case 2: - count = 2 << d_y_aspect_shift; - - for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) - { - if (pz[0] <= izi) - { - pz[0] = izi; - pdest[0] = pparticle->color; - } - - if (pz[1] <= izi) - { - pz[1] = izi; - pdest[1] = pparticle->color; - } - } - break; - - case 3: - count = 3 << d_y_aspect_shift; - - for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) - { - if (pz[0] <= izi) - { - pz[0] = izi; - pdest[0] = pparticle->color; - } - - if (pz[1] <= izi) - { - pz[1] = izi; - pdest[1] = pparticle->color; - } - - if (pz[2] <= izi) - { - pz[2] = izi; - pdest[2] = pparticle->color; - } - } - break; - - case 4: - count = 4 << d_y_aspect_shift; - - for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) - { - if (pz[0] <= izi) - { - pz[0] = izi; - pdest[0] = pparticle->color; - } - - if (pz[1] <= izi) - { - pz[1] = izi; - pdest[1] = pparticle->color; - } - - if (pz[2] <= izi) - { - pz[2] = izi; - pdest[2] = pparticle->color; - } - - if (pz[3] <= izi) - { - pz[3] = izi; - pdest[3] = pparticle->color; - } - } - break; - - default: - count = pix << d_y_aspect_shift; - - for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) - { - for (i=0 ; icolor; - } - } - } - break; - } -} - -#endif // !id386 - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_part.c: software driver module for drawing particles + +#include "quakedef.h" +#include "d_local.h" + + +/* +============== +D_EndParticles +============== +*/ +void D_EndParticles (void) +{ +// not used by software driver +} + + +/* +============== +D_StartParticles +============== +*/ +void D_StartParticles (void) +{ +// not used by software driver +} + + +#if !id386 + +/* +============== +D_DrawParticle +============== +*/ +void D_DrawParticle (particle_t *pparticle) +{ + vec3_t local, transformed; + float zi; + byte *pdest; + short *pz; + int i, izi, pix, count, u, v; + +// transform point + VectorSubtract (pparticle->org, r_origin, local); + + transformed[0] = DotProduct(local, r_pright); + transformed[1] = DotProduct(local, r_pup); + transformed[2] = DotProduct(local, r_ppn); + + if (transformed[2] < PARTICLE_Z_CLIP) + return; + +// project the point +// FIXME: preadjust xcenter and ycenter + zi = 1.0 / transformed[2]; + u = (int)(xcenter + zi * transformed[0] + 0.5); + v = (int)(ycenter - zi * transformed[1] + 0.5); + + if ((v > d_vrectbottom_particle) || + (u > d_vrectright_particle) || + (v < d_vrecty) || + (u < d_vrectx)) + { + return; + } + + pz = d_pzbuffer + (d_zwidth * v) + u; + pdest = d_viewbuffer + d_scantable[v] + u; + izi = (int)(zi * 0x8000); + + pix = izi >> d_pix_shift; + + if (pix < d_pix_min) + pix = d_pix_min; + else if (pix > d_pix_max) + pix = d_pix_max; + + switch (pix) + { + case 1: + count = 1 << d_y_aspect_shift; + + for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) + { + if (pz[0] <= izi) + { + pz[0] = izi; + pdest[0] = pparticle->color; + } + } + break; + + case 2: + count = 2 << d_y_aspect_shift; + + for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) + { + if (pz[0] <= izi) + { + pz[0] = izi; + pdest[0] = pparticle->color; + } + + if (pz[1] <= izi) + { + pz[1] = izi; + pdest[1] = pparticle->color; + } + } + break; + + case 3: + count = 3 << d_y_aspect_shift; + + for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) + { + if (pz[0] <= izi) + { + pz[0] = izi; + pdest[0] = pparticle->color; + } + + if (pz[1] <= izi) + { + pz[1] = izi; + pdest[1] = pparticle->color; + } + + if (pz[2] <= izi) + { + pz[2] = izi; + pdest[2] = pparticle->color; + } + } + break; + + case 4: + count = 4 << d_y_aspect_shift; + + for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) + { + if (pz[0] <= izi) + { + pz[0] = izi; + pdest[0] = pparticle->color; + } + + if (pz[1] <= izi) + { + pz[1] = izi; + pdest[1] = pparticle->color; + } + + if (pz[2] <= izi) + { + pz[2] = izi; + pdest[2] = pparticle->color; + } + + if (pz[3] <= izi) + { + pz[3] = izi; + pdest[3] = pparticle->color; + } + } + break; + + default: + count = pix << d_y_aspect_shift; + + for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) + { + for (i=0 ; icolor; + } + } + } + break; + } +} + +#endif // !id386 + diff --git a/WinQuake/d_parta.s b/WinQuake/d_parta.s index b32f1bc..560925d 100644 --- a/WinQuake/d_parta.s +++ b/WinQuake/d_parta.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_parta.s // x86 assembly-language 8-bpp particle-drawing code. diff --git a/WinQuake/d_polysa.s b/WinQuake/d_polysa.s index b238888..dc72679 100644 --- a/WinQuake/d_polysa.s +++ b/WinQuake/d_polysa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_polysa.s // x86 assembly-language polygon model drawing code diff --git a/WinQuake/d_polyse.c b/WinQuake/d_polyse.c index 9acd34b..ed2b6b6 100644 --- a/WinQuake/d_polyse.c +++ b/WinQuake/d_polyse.c @@ -1,1111 +1,1111 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_polyset.c: routines for drawing sets of polygons sharing the same -// texture (used for Alias models) - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - -// TODO: put in span spilling to shrink list size -// !!! if this is changed, it must be changed in d_polysa.s too !!! -#define DPS_MAXSPANS MAXHEIGHT+1 - // 1 extra for spanpackage that marks end - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct { - void *pdest; - short *pz; - int count; - byte *ptex; - int sfrac, tfrac, light, zi; -} spanpackage_t; - -typedef struct { - int isflattop; - int numleftedges; - int *pleftedgevert0; - int *pleftedgevert1; - int *pleftedgevert2; - int numrightedges; - int *prightedgevert0; - int *prightedgevert1; - int *prightedgevert2; -} edgetable; - -int r_p0[6], r_p1[6], r_p2[6]; - -byte *d_pcolormap; - -int d_aflatcolor; -int d_xdenom; - -edgetable *pedgetable; - -edgetable edgetables[12] = { - {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, - {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, - {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, - {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, - {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, - {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, - {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, - {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, - {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, - {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, - {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, - {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, -}; - -// FIXME: some of these can become statics -int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; -int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; -int r_zistepx, r_zistepy; -int d_aspancount, d_countextrastep; - -spanpackage_t *a_spans; -spanpackage_t *d_pedgespanpackage; -static int ystart; -byte *d_pdest, *d_ptex; -short *d_pz; -int d_sfrac, d_tfrac, d_light, d_zi; -int d_ptexextrastep, d_sfracextrastep; -int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; -int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; -int d_sfracbasestep, d_tfracbasestep; -int d_ziextrastep, d_zibasestep; -int d_pzextrastep, d_pzbasestep; - -typedef struct { - int quotient; - int remainder; -} adivtab_t; - -static adivtab_t adivtab[32*32] = { -#include "adivtab.h" -}; - -byte *skintable[MAX_LBM_HEIGHT]; -int skinwidth; -byte *skinstart; - -void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage); -void D_PolysetCalcGradients (int skinwidth); -void D_DrawSubdiv (void); -void D_DrawNonSubdiv (void); -void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3); -void D_PolysetSetEdgeTable (void); -void D_RasterizeAliasPolySmooth (void); -void D_PolysetScanLeftEdge (int height); - -#if !id386 - -/* -================ -D_PolysetDraw -================ -*/ -void D_PolysetDraw (void) -{ - spanpackage_t spans[DPS_MAXSPANS + 1 + - ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1]; - // one extra because of cache line pretouching - - a_spans = (spanpackage_t *) - (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - - if (r_affinetridesc.drawtype) - { - D_DrawSubdiv (); - } - else - { - D_DrawNonSubdiv (); - } -} - - -/* -================ -D_PolysetDrawFinalVerts -================ -*/ -void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts) -{ - int i, z; - short *zbuf; - - for (i=0 ; iv[0] < r_refdef.vrectright) && - (fv->v[1] < r_refdef.vrectbottom)) - { - z = fv->v[5]>>16; - zbuf = zspantable[fv->v[1]] + fv->v[0]; - if (z >= *zbuf) - { - int pix; - - *zbuf = z; - pix = skintable[fv->v[3]>>16][fv->v[2]>>16]; - pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ]; - d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix; - } - } - } -} - - -/* -================ -D_DrawSubdiv -================ -*/ -void D_DrawSubdiv (void) -{ - mtriangle_t *ptri; - finalvert_t *pfv, *index0, *index1, *index2; - int i; - int lnumtriangles; - - pfv = r_affinetridesc.pfinalverts; - ptri = r_affinetridesc.ptriangles; - lnumtriangles = r_affinetridesc.numtriangles; - - for (i=0 ; iv[1]-index1->v[1]) * - (index0->v[0]-index2->v[0]) - - (index0->v[0]-index1->v[0]) * - (index0->v[1]-index2->v[1])) >= 0) - { - continue; - } - - d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00]; - - if (ptri[i].facesfront) - { - D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); - } - else - { - int s0, s1, s2; - - s0 = index0->v[2]; - s1 = index1->v[2]; - s2 = index2->v[2]; - - if (index0->flags & ALIAS_ONSEAM) - index0->v[2] += r_affinetridesc.seamfixupX16; - if (index1->flags & ALIAS_ONSEAM) - index1->v[2] += r_affinetridesc.seamfixupX16; - if (index2->flags & ALIAS_ONSEAM) - index2->v[2] += r_affinetridesc.seamfixupX16; - - D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); - - index0->v[2] = s0; - index1->v[2] = s1; - index2->v[2] = s2; - } - } -} - - -/* -================ -D_DrawNonSubdiv -================ -*/ -void D_DrawNonSubdiv (void) -{ - mtriangle_t *ptri; - finalvert_t *pfv, *index0, *index1, *index2; - int i; - int lnumtriangles; - - pfv = r_affinetridesc.pfinalverts; - ptri = r_affinetridesc.ptriangles; - lnumtriangles = r_affinetridesc.numtriangles; - - for (i=0 ; ivertindex[0]; - index1 = pfv + ptri->vertindex[1]; - index2 = pfv + ptri->vertindex[2]; - - d_xdenom = (index0->v[1]-index1->v[1]) * - (index0->v[0]-index2->v[0]) - - (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]); - - if (d_xdenom >= 0) - { - continue; - } - - r_p0[0] = index0->v[0]; // u - r_p0[1] = index0->v[1]; // v - r_p0[2] = index0->v[2]; // s - r_p0[3] = index0->v[3]; // t - r_p0[4] = index0->v[4]; // light - r_p0[5] = index0->v[5]; // iz - - r_p1[0] = index1->v[0]; - r_p1[1] = index1->v[1]; - r_p1[2] = index1->v[2]; - r_p1[3] = index1->v[3]; - r_p1[4] = index1->v[4]; - r_p1[5] = index1->v[5]; - - r_p2[0] = index2->v[0]; - r_p2[1] = index2->v[1]; - r_p2[2] = index2->v[2]; - r_p2[3] = index2->v[3]; - r_p2[4] = index2->v[4]; - r_p2[5] = index2->v[5]; - - if (!ptri->facesfront) - { - if (index0->flags & ALIAS_ONSEAM) - r_p0[2] += r_affinetridesc.seamfixupX16; - if (index1->flags & ALIAS_ONSEAM) - r_p1[2] += r_affinetridesc.seamfixupX16; - if (index2->flags & ALIAS_ONSEAM) - r_p2[2] += r_affinetridesc.seamfixupX16; - } - - D_PolysetSetEdgeTable (); - D_RasterizeAliasPolySmooth (); - } -} - - -/* -================ -D_PolysetRecursiveTriangle -================ -*/ -void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3) -{ - int *temp; - int d; - int new[6]; - int z; - short *zbuf; - - d = lp2[0] - lp1[0]; - if (d < -1 || d > 1) - goto split; - d = lp2[1] - lp1[1]; - if (d < -1 || d > 1) - goto split; - - d = lp3[0] - lp2[0]; - if (d < -1 || d > 1) - goto split2; - d = lp3[1] - lp2[1]; - if (d < -1 || d > 1) - goto split2; - - d = lp1[0] - lp3[0]; - if (d < -1 || d > 1) - goto split3; - d = lp1[1] - lp3[1]; - if (d < -1 || d > 1) - { -split3: - temp = lp1; - lp1 = lp3; - lp3 = lp2; - lp2 = temp; - - goto split; - } - - return; // entire tri is filled - -split2: - temp = lp1; - lp1 = lp2; - lp2 = lp3; - lp3 = temp; - -split: -// split this edge - new[0] = (lp1[0] + lp2[0]) >> 1; - new[1] = (lp1[1] + lp2[1]) >> 1; - new[2] = (lp1[2] + lp2[2]) >> 1; - new[3] = (lp1[3] + lp2[3]) >> 1; - new[5] = (lp1[5] + lp2[5]) >> 1; - -// draw the point if splitting a leading edge - if (lp2[1] > lp1[1]) - goto nodraw; - if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) - goto nodraw; - - - z = new[5]>>16; - zbuf = zspantable[new[1]] + new[0]; - if (z >= *zbuf) - { - int pix; - - *zbuf = z; - pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; - d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; - } - -nodraw: -// recursively continue - D_PolysetRecursiveTriangle (lp3, lp1, new); - D_PolysetRecursiveTriangle (lp3, new, lp2); -} - -#endif // !id386 - - -/* -================ -D_PolysetUpdateTables -================ -*/ -void D_PolysetUpdateTables (void) -{ - int i; - byte *s; - - if (r_affinetridesc.skinwidth != skinwidth || - r_affinetridesc.pskin != skinstart) - { - skinwidth = r_affinetridesc.skinwidth; - skinstart = r_affinetridesc.pskin; - s = skinstart; - for (i=0 ; ipdest = d_pdest; - d_pedgespanpackage->pz = d_pz; - d_pedgespanpackage->count = d_aspancount; - d_pedgespanpackage->ptex = d_ptex; - - d_pedgespanpackage->sfrac = d_sfrac; - d_pedgespanpackage->tfrac = d_tfrac; - - // FIXME: need to clamp l, s, t, at both ends? - d_pedgespanpackage->light = d_light; - d_pedgespanpackage->zi = d_zi; - - d_pedgespanpackage++; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_pdest += d_pdestextrastep; - d_pz += d_pzextrastep; - d_aspancount += d_countextrastep; - d_ptex += d_ptexextrastep; - d_sfrac += d_sfracextrastep; - d_ptex += d_sfrac >> 16; - - d_sfrac &= 0xFFFF; - d_tfrac += d_tfracextrastep; - if (d_tfrac & 0x10000) - { - d_ptex += r_affinetridesc.skinwidth; - d_tfrac &= 0xFFFF; - } - d_light += d_lightextrastep; - d_zi += d_ziextrastep; - errorterm -= erroradjustdown; - } - else - { - d_pdest += d_pdestbasestep; - d_pz += d_pzbasestep; - d_aspancount += ubasestep; - d_ptex += d_ptexbasestep; - d_sfrac += d_sfracbasestep; - d_ptex += d_sfrac >> 16; - d_sfrac &= 0xFFFF; - d_tfrac += d_tfracbasestep; - if (d_tfrac & 0x10000) - { - d_ptex += r_affinetridesc.skinwidth; - d_tfrac &= 0xFFFF; - } - d_light += d_lightbasestep; - d_zi += d_zibasestep; - } - } while (--height); -} - -#endif // !id386 - - -/* -=================== -D_PolysetSetUpForLineScan -==================== -*/ -void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, - fixed8_t endvertu, fixed8_t endvertv) -{ - double dm, dn; - int tm, tn; - adivtab_t *ptemp; - -// TODO: implement x86 version - - errorterm = -1; - - tm = endvertu - startvertu; - tn = endvertv - startvertv; - - if (((tm <= 16) && (tm >= -15)) && - ((tn <= 16) && (tn >= -15))) - { - ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; - ubasestep = ptemp->quotient; - erroradjustup = ptemp->remainder; - erroradjustdown = tn; - } - else - { - dm = (double)tm; - dn = (double)tn; - - FloorDivMod (dm, dn, &ubasestep, &erroradjustup); - - erroradjustdown = dn; - } -} - - -#if !id386 - -/* -================ -D_PolysetCalcGradients -================ -*/ -void D_PolysetCalcGradients (int skinwidth) -{ - float xstepdenominv, ystepdenominv, t0, t1; - float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; - - p00_minus_p20 = r_p0[0] - r_p2[0]; - p01_minus_p21 = r_p0[1] - r_p2[1]; - p10_minus_p20 = r_p1[0] - r_p2[0]; - p11_minus_p21 = r_p1[1] - r_p2[1]; - - xstepdenominv = 1.0 / (float)d_xdenom; - - ystepdenominv = -xstepdenominv; - -// ceil () for light so positive steps are exaggerated, negative steps -// diminished, pushing us away from underflow toward overflow. Underflow is -// very visible, overflow is very unlikely, because of ambient lighting - t0 = r_p0[4] - r_p2[4]; - t1 = r_p1[4] - r_p2[4]; - r_lstepx = (int) - ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); - r_lstepy = (int) - ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); - - t0 = r_p0[2] - r_p2[2]; - t1 = r_p1[2] - r_p2[2]; - r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * - ystepdenominv); - - t0 = r_p0[3] - r_p2[3]; - t1 = r_p1[3] - r_p2[3]; - r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * - ystepdenominv); - - t0 = r_p0[5] - r_p2[5]; - t1 = r_p1[5] - r_p2[5]; - r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * - ystepdenominv); - -#if id386 - a_sstepxfrac = r_sstepx << 16; - a_tstepxfrac = r_tstepx << 16; -#else - a_sstepxfrac = r_sstepx & 0xFFFF; - a_tstepxfrac = r_tstepx & 0xFFFF; -#endif - - a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); -} - -#endif // !id386 - - -#if 0 -byte gelmap[256]; -void InitGel (byte *palette) -{ - int i; - int r; - - for (i=0 ; i<256 ; i++) - { -// r = (palette[i*3]>>4); - r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3); - gelmap[i] = /* 64 */ 0 + r; - } -} -#endif - - -#if !id386 - -/* -================ -D_PolysetDrawSpans8 -================ -*/ -void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage) -{ - int lcount; - byte *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - { - d_aspancount += ubasestep; - } - - if (lcount) - { - lpdest = pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) >= *lpz) - { - *lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)]; -// gel mapping *lpdest = gelmap[*lpdest]; - *lpz = lzi >> 16; - } - lpdest++; - lzi += r_zistepx; - lpz++; - llight += r_lstepx; - lptex += a_ststepxwhole; - lsfrac += a_sstepxfrac; - lptex += lsfrac >> 16; - lsfrac &= 0xFFFF; - ltfrac += a_tstepxfrac; - if (ltfrac & 0x10000) - { - lptex += r_affinetridesc.skinwidth; - ltfrac &= 0xFFFF; - } - } while (--lcount); - } - - pspanpackage++; - } while (pspanpackage->count != -999999); -} -#endif // !id386 - - -/* -================ -D_PolysetFillSpans8 -================ -*/ -void D_PolysetFillSpans8 (spanpackage_t *pspanpackage) -{ - int color; - -// FIXME: do z buffering - - color = d_aflatcolor++; - - while (1) - { - int lcount; - byte *lpdest; - - lcount = pspanpackage->count; - - if (lcount == -1) - return; - - if (lcount) - { - lpdest = pspanpackage->pdest; - - do - { - *lpdest++ = color; - } while (--lcount); - } - - pspanpackage++; - } -} - -/* -================ -D_RasterizeAliasPolySmooth -================ -*/ -void D_RasterizeAliasPolySmooth (void) -{ - int initialleftheight, initialrightheight; - int *plefttop, *prighttop, *pleftbottom, *prightbottom; - int working_lstepx, originalcount; - - plefttop = pedgetable->pleftedgevert0; - prighttop = pedgetable->prightedgevert0; - - pleftbottom = pedgetable->pleftedgevert1; - prightbottom = pedgetable->prightedgevert1; - - initialleftheight = pleftbottom[1] - plefttop[1]; - initialrightheight = prightbottom[1] - prighttop[1]; - -// -// set the s, t, and light gradients, which are consistent across the triangle -// because being a triangle, things are affine -// - D_PolysetCalcGradients (r_affinetridesc.skinwidth); - -// -// rasterize the polygon -// - -// -// scan out the top (and possibly only) part of the left edge -// - d_pedgespanpackage = a_spans; - - ystart = plefttop[1]; - d_aspancount = plefttop[0] - prighttop[0]; - - d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + - (plefttop[3] >> 16) * r_affinetridesc.skinwidth; -#if id386 - d_sfrac = (plefttop[2] & 0xFFFF) << 16; - d_tfrac = (plefttop[3] & 0xFFFF) << 16; -#else - d_sfrac = plefttop[2] & 0xFFFF; - d_tfrac = plefttop[3] & 0xFFFF; -#endif - d_light = plefttop[4]; - d_zi = plefttop[5]; - - d_pdest = (byte *)d_viewbuffer + - ystart * screenwidth + plefttop[0]; - d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; - - if (initialleftheight == 1) - { - d_pedgespanpackage->pdest = d_pdest; - d_pedgespanpackage->pz = d_pz; - d_pedgespanpackage->count = d_aspancount; - d_pedgespanpackage->ptex = d_ptex; - - d_pedgespanpackage->sfrac = d_sfrac; - d_pedgespanpackage->tfrac = d_tfrac; - - // FIXME: need to clamp l, s, t, at both ends? - d_pedgespanpackage->light = d_light; - d_pedgespanpackage->zi = d_zi; - - d_pedgespanpackage++; - } - else - { - D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], - pleftbottom[0], pleftbottom[1]); - - #if id386 - d_pzbasestep = (d_zwidth + ubasestep) << 1; - d_pzextrastep = d_pzbasestep + 2; - #else - d_pzbasestep = d_zwidth + ubasestep; - d_pzextrastep = d_pzbasestep + 1; - #endif - - d_pdestbasestep = screenwidth + ubasestep; - d_pdestextrastep = d_pdestbasestep + 1; - - // TODO: can reuse partial expressions here - - // for negative steps in x along left edge, bias toward overflow rather than - // underflow (sort of turning the floor () we did in the gradient calcs into - // ceil (), but plus a little bit) - if (ubasestep < 0) - working_lstepx = r_lstepx - 1; - else - working_lstepx = r_lstepx; - - d_countextrastep = ubasestep + 1; - d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + - ((r_tstepy + r_tstepx * ubasestep) >> 16) * - r_affinetridesc.skinwidth; - #if id386 - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; - #else - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; - #endif - d_lightbasestep = r_lstepy + working_lstepx * ubasestep; - d_zibasestep = r_zistepy + r_zistepx * ubasestep; - - d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + - ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * - r_affinetridesc.skinwidth; - #if id386 - d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; - d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; - #else - d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; - d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; - #endif - d_lightextrastep = d_lightbasestep + working_lstepx; - d_ziextrastep = d_zibasestep + r_zistepx; - - D_PolysetScanLeftEdge (initialleftheight); - } - -// -// scan out the bottom part of the left edge, if it exists -// - if (pedgetable->numleftedges == 2) - { - int height; - - plefttop = pleftbottom; - pleftbottom = pedgetable->pleftedgevert2; - - height = pleftbottom[1] - plefttop[1]; - -// TODO: make this a function; modularize this function in general - - ystart = plefttop[1]; - d_aspancount = plefttop[0] - prighttop[0]; - d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + - (plefttop[3] >> 16) * r_affinetridesc.skinwidth; - d_sfrac = 0; - d_tfrac = 0; - d_light = plefttop[4]; - d_zi = plefttop[5]; - - d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0]; - d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; - - if (height == 1) - { - d_pedgespanpackage->pdest = d_pdest; - d_pedgespanpackage->pz = d_pz; - d_pedgespanpackage->count = d_aspancount; - d_pedgespanpackage->ptex = d_ptex; - - d_pedgespanpackage->sfrac = d_sfrac; - d_pedgespanpackage->tfrac = d_tfrac; - - // FIXME: need to clamp l, s, t, at both ends? - d_pedgespanpackage->light = d_light; - d_pedgespanpackage->zi = d_zi; - - d_pedgespanpackage++; - } - else - { - D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], - pleftbottom[0], pleftbottom[1]); - - d_pdestbasestep = screenwidth + ubasestep; - d_pdestextrastep = d_pdestbasestep + 1; - - #if id386 - d_pzbasestep = (d_zwidth + ubasestep) << 1; - d_pzextrastep = d_pzbasestep + 2; - #else - d_pzbasestep = d_zwidth + ubasestep; - d_pzextrastep = d_pzbasestep + 1; - #endif - - if (ubasestep < 0) - working_lstepx = r_lstepx - 1; - else - working_lstepx = r_lstepx; - - d_countextrastep = ubasestep + 1; - d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + - ((r_tstepy + r_tstepx * ubasestep) >> 16) * - r_affinetridesc.skinwidth; - #if id386 - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; - #else - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; - #endif - d_lightbasestep = r_lstepy + working_lstepx * ubasestep; - d_zibasestep = r_zistepy + r_zistepx * ubasestep; - - d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + - ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * - r_affinetridesc.skinwidth; - #if id386 - d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; - d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; - #else - d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; - d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; - #endif - d_lightextrastep = d_lightbasestep + working_lstepx; - d_ziextrastep = d_zibasestep + r_zistepx; - - D_PolysetScanLeftEdge (height); - } - } - -// scan out the top (and possibly only) part of the right edge, updating the -// count field - d_pedgespanpackage = a_spans; - - D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], - prightbottom[0], prightbottom[1]); - d_aspancount = 0; - d_countextrastep = ubasestep + 1; - originalcount = a_spans[initialrightheight].count; - a_spans[initialrightheight].count = -999999; // mark end of the spanpackages - D_PolysetDrawSpans8 (a_spans); - -// scan out the bottom part of the right edge, if it exists - if (pedgetable->numrightedges == 2) - { - int height; - spanpackage_t *pstart; - - pstart = a_spans + initialrightheight; - pstart->count = originalcount; - - d_aspancount = prightbottom[0] - prighttop[0]; - - prighttop = prightbottom; - prightbottom = pedgetable->prightedgevert2; - - height = prightbottom[1] - prighttop[1]; - - D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], - prightbottom[0], prightbottom[1]); - - d_countextrastep = ubasestep + 1; - a_spans[initialrightheight + height].count = -999999; - // mark end of the spanpackages - D_PolysetDrawSpans8 (pstart); - } -} - - -/* -================ -D_PolysetSetEdgeTable -================ -*/ -void D_PolysetSetEdgeTable (void) -{ - int edgetableindex; - - edgetableindex = 0; // assume the vertices are already in - // top to bottom order - -// -// determine which edges are right & left, and the order in which -// to rasterize them -// - if (r_p0[1] >= r_p1[1]) - { - if (r_p0[1] == r_p1[1]) - { - if (r_p0[1] < r_p2[1]) - pedgetable = &edgetables[2]; - else - pedgetable = &edgetables[5]; - - return; - } - else - { - edgetableindex = 1; - } - } - - if (r_p0[1] == r_p2[1]) - { - if (edgetableindex) - pedgetable = &edgetables[8]; - else - pedgetable = &edgetables[9]; - - return; - } - else if (r_p1[1] == r_p2[1]) - { - if (edgetableindex) - pedgetable = &edgetables[10]; - else - pedgetable = &edgetables[11]; - - return; - } - - if (r_p0[1] > r_p2[1]) - edgetableindex += 2; - - if (r_p1[1] > r_p2[1]) - edgetableindex += 4; - - pedgetable = &edgetables[edgetableindex]; -} - - -#if 0 - -void D_PolysetRecursiveDrawLine (int *lp1, int *lp2) -{ - int d; - int new[6]; - int ofs; - - d = lp2[0] - lp1[0]; - if (d < -1 || d > 1) - goto split; - d = lp2[1] - lp1[1]; - if (d < -1 || d > 1) - goto split; - - return; // line is completed - -split: -// split this edge - new[0] = (lp1[0] + lp2[0]) >> 1; - new[1] = (lp1[1] + lp2[1]) >> 1; - new[5] = (lp1[5] + lp2[5]) >> 1; - new[2] = (lp1[2] + lp2[2]) >> 1; - new[3] = (lp1[3] + lp2[3]) >> 1; - new[4] = (lp1[4] + lp2[4]) >> 1; - -// draw the point - ofs = d_scantable[new[1]] + new[0]; - if (new[5] > d_pzbuffer[ofs]) - { - int pix; - - d_pzbuffer[ofs] = new[5]; - pix = skintable[new[3]>>16][new[2]>>16]; -// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)]; - d_viewbuffer[ofs] = pix; - } - -// recursively continue - D_PolysetRecursiveDrawLine (lp1, new); - D_PolysetRecursiveDrawLine (new, lp2); -} - -void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3) -{ - int d; - int new[4]; - - d = lp2[0] - lp1[0]; - if (d < -1 || d > 1) - goto split; - d = lp2[1] - lp1[1]; - if (d < -1 || d > 1) - goto split; - return; - -split: -// split this edge - new[0] = (lp1[0] + lp2[0]) >> 1; - new[1] = (lp1[1] + lp2[1]) >> 1; - new[5] = (lp1[5] + lp2[5]) >> 1; - new[2] = (lp1[2] + lp2[2]) >> 1; - new[3] = (lp1[3] + lp2[3]) >> 1; - new[4] = (lp1[4] + lp2[4]) >> 1; - - D_PolysetRecursiveDrawLine (new, lp3); - -// recursively continue - D_PolysetRecursiveTriangle (lp1, new, lp3); - D_PolysetRecursiveTriangle (new, lp2, lp3); -} - -#endif - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_polyset.c: routines for drawing sets of polygons sharing the same +// texture (used for Alias models) + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" + +// TODO: put in span spilling to shrink list size +// !!! if this is changed, it must be changed in d_polysa.s too !!! +#define DPS_MAXSPANS MAXHEIGHT+1 + // 1 extra for spanpackage that marks end + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct { + void *pdest; + short *pz; + int count; + byte *ptex; + int sfrac, tfrac, light, zi; +} spanpackage_t; + +typedef struct { + int isflattop; + int numleftedges; + int *pleftedgevert0; + int *pleftedgevert1; + int *pleftedgevert2; + int numrightedges; + int *prightedgevert0; + int *prightedgevert1; + int *prightedgevert2; +} edgetable; + +int r_p0[6], r_p1[6], r_p2[6]; + +byte *d_pcolormap; + +int d_aflatcolor; +int d_xdenom; + +edgetable *pedgetable; + +edgetable edgetables[12] = { + {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, + {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, + {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, + {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, + {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, + {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, + {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, + {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, + {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, + {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, +}; + +// FIXME: some of these can become statics +int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; +int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; +int r_zistepx, r_zistepy; +int d_aspancount, d_countextrastep; + +spanpackage_t *a_spans; +spanpackage_t *d_pedgespanpackage; +static int ystart; +byte *d_pdest, *d_ptex; +short *d_pz; +int d_sfrac, d_tfrac, d_light, d_zi; +int d_ptexextrastep, d_sfracextrastep; +int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; +int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; +int d_sfracbasestep, d_tfracbasestep; +int d_ziextrastep, d_zibasestep; +int d_pzextrastep, d_pzbasestep; + +typedef struct { + int quotient; + int remainder; +} adivtab_t; + +static adivtab_t adivtab[32*32] = { +#include "adivtab.h" +}; + +byte *skintable[MAX_LBM_HEIGHT]; +int skinwidth; +byte *skinstart; + +void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage); +void D_PolysetCalcGradients (int skinwidth); +void D_DrawSubdiv (void); +void D_DrawNonSubdiv (void); +void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3); +void D_PolysetSetEdgeTable (void); +void D_RasterizeAliasPolySmooth (void); +void D_PolysetScanLeftEdge (int height); + +#if !id386 + +/* +================ +D_PolysetDraw +================ +*/ +void D_PolysetDraw (void) +{ + spanpackage_t spans[DPS_MAXSPANS + 1 + + ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1]; + // one extra because of cache line pretouching + + a_spans = (spanpackage_t *) + (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + + if (r_affinetridesc.drawtype) + { + D_DrawSubdiv (); + } + else + { + D_DrawNonSubdiv (); + } +} + + +/* +================ +D_PolysetDrawFinalVerts +================ +*/ +void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts) +{ + int i, z; + short *zbuf; + + for (i=0 ; iv[0] < r_refdef.vrectright) && + (fv->v[1] < r_refdef.vrectbottom)) + { + z = fv->v[5]>>16; + zbuf = zspantable[fv->v[1]] + fv->v[0]; + if (z >= *zbuf) + { + int pix; + + *zbuf = z; + pix = skintable[fv->v[3]>>16][fv->v[2]>>16]; + pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ]; + d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix; + } + } + } +} + + +/* +================ +D_DrawSubdiv +================ +*/ +void D_DrawSubdiv (void) +{ + mtriangle_t *ptri; + finalvert_t *pfv, *index0, *index1, *index2; + int i; + int lnumtriangles; + + pfv = r_affinetridesc.pfinalverts; + ptri = r_affinetridesc.ptriangles; + lnumtriangles = r_affinetridesc.numtriangles; + + for (i=0 ; iv[1]-index1->v[1]) * + (index0->v[0]-index2->v[0]) - + (index0->v[0]-index1->v[0]) * + (index0->v[1]-index2->v[1])) >= 0) + { + continue; + } + + d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00]; + + if (ptri[i].facesfront) + { + D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); + } + else + { + int s0, s1, s2; + + s0 = index0->v[2]; + s1 = index1->v[2]; + s2 = index2->v[2]; + + if (index0->flags & ALIAS_ONSEAM) + index0->v[2] += r_affinetridesc.seamfixupX16; + if (index1->flags & ALIAS_ONSEAM) + index1->v[2] += r_affinetridesc.seamfixupX16; + if (index2->flags & ALIAS_ONSEAM) + index2->v[2] += r_affinetridesc.seamfixupX16; + + D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); + + index0->v[2] = s0; + index1->v[2] = s1; + index2->v[2] = s2; + } + } +} + + +/* +================ +D_DrawNonSubdiv +================ +*/ +void D_DrawNonSubdiv (void) +{ + mtriangle_t *ptri; + finalvert_t *pfv, *index0, *index1, *index2; + int i; + int lnumtriangles; + + pfv = r_affinetridesc.pfinalverts; + ptri = r_affinetridesc.ptriangles; + lnumtriangles = r_affinetridesc.numtriangles; + + for (i=0 ; ivertindex[0]; + index1 = pfv + ptri->vertindex[1]; + index2 = pfv + ptri->vertindex[2]; + + d_xdenom = (index0->v[1]-index1->v[1]) * + (index0->v[0]-index2->v[0]) - + (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]); + + if (d_xdenom >= 0) + { + continue; + } + + r_p0[0] = index0->v[0]; // u + r_p0[1] = index0->v[1]; // v + r_p0[2] = index0->v[2]; // s + r_p0[3] = index0->v[3]; // t + r_p0[4] = index0->v[4]; // light + r_p0[5] = index0->v[5]; // iz + + r_p1[0] = index1->v[0]; + r_p1[1] = index1->v[1]; + r_p1[2] = index1->v[2]; + r_p1[3] = index1->v[3]; + r_p1[4] = index1->v[4]; + r_p1[5] = index1->v[5]; + + r_p2[0] = index2->v[0]; + r_p2[1] = index2->v[1]; + r_p2[2] = index2->v[2]; + r_p2[3] = index2->v[3]; + r_p2[4] = index2->v[4]; + r_p2[5] = index2->v[5]; + + if (!ptri->facesfront) + { + if (index0->flags & ALIAS_ONSEAM) + r_p0[2] += r_affinetridesc.seamfixupX16; + if (index1->flags & ALIAS_ONSEAM) + r_p1[2] += r_affinetridesc.seamfixupX16; + if (index2->flags & ALIAS_ONSEAM) + r_p2[2] += r_affinetridesc.seamfixupX16; + } + + D_PolysetSetEdgeTable (); + D_RasterizeAliasPolySmooth (); + } +} + + +/* +================ +D_PolysetRecursiveTriangle +================ +*/ +void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3) +{ + int *temp; + int d; + int new[6]; + int z; + short *zbuf; + + d = lp2[0] - lp1[0]; + if (d < -1 || d > 1) + goto split; + d = lp2[1] - lp1[1]; + if (d < -1 || d > 1) + goto split; + + d = lp3[0] - lp2[0]; + if (d < -1 || d > 1) + goto split2; + d = lp3[1] - lp2[1]; + if (d < -1 || d > 1) + goto split2; + + d = lp1[0] - lp3[0]; + if (d < -1 || d > 1) + goto split3; + d = lp1[1] - lp3[1]; + if (d < -1 || d > 1) + { +split3: + temp = lp1; + lp1 = lp3; + lp3 = lp2; + lp2 = temp; + + goto split; + } + + return; // entire tri is filled + +split2: + temp = lp1; + lp1 = lp2; + lp2 = lp3; + lp3 = temp; + +split: +// split this edge + new[0] = (lp1[0] + lp2[0]) >> 1; + new[1] = (lp1[1] + lp2[1]) >> 1; + new[2] = (lp1[2] + lp2[2]) >> 1; + new[3] = (lp1[3] + lp2[3]) >> 1; + new[5] = (lp1[5] + lp2[5]) >> 1; + +// draw the point if splitting a leading edge + if (lp2[1] > lp1[1]) + goto nodraw; + if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) + goto nodraw; + + + z = new[5]>>16; + zbuf = zspantable[new[1]] + new[0]; + if (z >= *zbuf) + { + int pix; + + *zbuf = z; + pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; + d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; + } + +nodraw: +// recursively continue + D_PolysetRecursiveTriangle (lp3, lp1, new); + D_PolysetRecursiveTriangle (lp3, new, lp2); +} + +#endif // !id386 + + +/* +================ +D_PolysetUpdateTables +================ +*/ +void D_PolysetUpdateTables (void) +{ + int i; + byte *s; + + if (r_affinetridesc.skinwidth != skinwidth || + r_affinetridesc.pskin != skinstart) + { + skinwidth = r_affinetridesc.skinwidth; + skinstart = r_affinetridesc.pskin; + s = skinstart; + for (i=0 ; ipdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_pdest += d_pdestextrastep; + d_pz += d_pzextrastep; + d_aspancount += d_countextrastep; + d_ptex += d_ptexextrastep; + d_sfrac += d_sfracextrastep; + d_ptex += d_sfrac >> 16; + + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracextrastep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightextrastep; + d_zi += d_ziextrastep; + errorterm -= erroradjustdown; + } + else + { + d_pdest += d_pdestbasestep; + d_pz += d_pzbasestep; + d_aspancount += ubasestep; + d_ptex += d_ptexbasestep; + d_sfrac += d_sfracbasestep; + d_ptex += d_sfrac >> 16; + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracbasestep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightbasestep; + d_zi += d_zibasestep; + } + } while (--height); +} + +#endif // !id386 + + +/* +=================== +D_PolysetSetUpForLineScan +==================== +*/ +void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, + fixed8_t endvertu, fixed8_t endvertv) +{ + double dm, dn; + int tm, tn; + adivtab_t *ptemp; + +// TODO: implement x86 version + + errorterm = -1; + + tm = endvertu - startvertu; + tn = endvertv - startvertv; + + if (((tm <= 16) && (tm >= -15)) && + ((tn <= 16) && (tn >= -15))) + { + ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; + ubasestep = ptemp->quotient; + erroradjustup = ptemp->remainder; + erroradjustdown = tn; + } + else + { + dm = (double)tm; + dn = (double)tn; + + FloorDivMod (dm, dn, &ubasestep, &erroradjustup); + + erroradjustdown = dn; + } +} + + +#if !id386 + +/* +================ +D_PolysetCalcGradients +================ +*/ +void D_PolysetCalcGradients (int skinwidth) +{ + float xstepdenominv, ystepdenominv, t0, t1; + float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + + xstepdenominv = 1.0 / (float)d_xdenom; + + ystepdenominv = -xstepdenominv; + +// ceil () for light so positive steps are exaggerated, negative steps +// diminished, pushing us away from underflow toward overflow. Underflow is +// very visible, overflow is very unlikely, because of ambient lighting + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + +#if id386 + a_sstepxfrac = r_sstepx << 16; + a_tstepxfrac = r_tstepx << 16; +#else + a_sstepxfrac = r_sstepx & 0xFFFF; + a_tstepxfrac = r_tstepx & 0xFFFF; +#endif + + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); +} + +#endif // !id386 + + +#if 0 +byte gelmap[256]; +void InitGel (byte *palette) +{ + int i; + int r; + + for (i=0 ; i<256 ; i++) + { +// r = (palette[i*3]>>4); + r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3); + gelmap[i] = /* 64 */ 0 + r; + } +} +#endif + + +#if !id386 + +/* +================ +D_PolysetDrawSpans8 +================ +*/ +void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + *lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)]; +// gel mapping *lpdest = gelmap[*lpdest]; + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} +#endif // !id386 + + +/* +================ +D_PolysetFillSpans8 +================ +*/ +void D_PolysetFillSpans8 (spanpackage_t *pspanpackage) +{ + int color; + +// FIXME: do z buffering + + color = d_aflatcolor++; + + while (1) + { + int lcount; + byte *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) + { + lpdest = pspanpackage->pdest; + + do + { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } +} + +/* +================ +D_RasterizeAliasPolySmooth +================ +*/ +void D_RasterizeAliasPolySmooth (void) +{ + int initialleftheight, initialrightheight; + int *plefttop, *prighttop, *pleftbottom, *prightbottom; + int working_lstepx, originalcount; + + plefttop = pedgetable->pleftedgevert0; + prighttop = pedgetable->prightedgevert0; + + pleftbottom = pedgetable->pleftedgevert1; + prightbottom = pedgetable->prightedgevert1; + + initialleftheight = pleftbottom[1] - plefttop[1]; + initialrightheight = prightbottom[1] - prighttop[1]; + +// +// set the s, t, and light gradients, which are consistent across the triangle +// because being a triangle, things are affine +// + D_PolysetCalcGradients (r_affinetridesc.skinwidth); + +// +// rasterize the polygon +// + +// +// scan out the top (and possibly only) part of the left edge +// + d_pedgespanpackage = a_spans; + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; +#if id386 + d_sfrac = (plefttop[2] & 0xFFFF) << 16; + d_tfrac = (plefttop[3] & 0xFFFF) << 16; +#else + d_sfrac = plefttop[2] & 0xFFFF; + d_tfrac = plefttop[3] & 0xFFFF; +#endif + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (byte *)d_viewbuffer + + ystart * screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (initialleftheight == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + #if id386 + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + #else + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + #endif + + d_pdestbasestep = screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + + // TODO: can reuse partial expressions here + + // for negative steps in x along left edge, bias toward overflow rather than + // underflow (sort of turning the floor () we did in the gradient calcs into + // ceil (), but plus a little bit) + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; + #if id386 + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + #else + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + #endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; + #if id386 + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; + #else + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; + #endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + + D_PolysetScanLeftEdge (initialleftheight); + } + +// +// scan out the bottom part of the left edge, if it exists +// + if (pedgetable->numleftedges == 2) + { + int height; + + plefttop = pleftbottom; + pleftbottom = pedgetable->pleftedgevert2; + + height = pleftbottom[1] - plefttop[1]; + +// TODO: make this a function; modularize this function in general + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = 0; + d_tfrac = 0; + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (height == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + d_pdestbasestep = screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + + #if id386 + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + #else + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + #endif + + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; + #if id386 + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + #else + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + #endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; + #if id386 + d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; + d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; + #else + d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; + #endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + + D_PolysetScanLeftEdge (height); + } + } + +// scan out the top (and possibly only) part of the right edge, updating the +// count field + d_pedgespanpackage = a_spans; + + D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + d_aspancount = 0; + d_countextrastep = ubasestep + 1; + originalcount = a_spans[initialrightheight].count; + a_spans[initialrightheight].count = -999999; // mark end of the spanpackages + D_PolysetDrawSpans8 (a_spans); + +// scan out the bottom part of the right edge, if it exists + if (pedgetable->numrightedges == 2) + { + int height; + spanpackage_t *pstart; + + pstart = a_spans + initialrightheight; + pstart->count = originalcount; + + d_aspancount = prightbottom[0] - prighttop[0]; + + prighttop = prightbottom; + prightbottom = pedgetable->prightedgevert2; + + height = prightbottom[1] - prighttop[1]; + + D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + + d_countextrastep = ubasestep + 1; + a_spans[initialrightheight + height].count = -999999; + // mark end of the spanpackages + D_PolysetDrawSpans8 (pstart); + } +} + + +/* +================ +D_PolysetSetEdgeTable +================ +*/ +void D_PolysetSetEdgeTable (void) +{ + int edgetableindex; + + edgetableindex = 0; // assume the vertices are already in + // top to bottom order + +// +// determine which edges are right & left, and the order in which +// to rasterize them +// + if (r_p0[1] >= r_p1[1]) + { + if (r_p0[1] == r_p1[1]) + { + if (r_p0[1] < r_p2[1]) + pedgetable = &edgetables[2]; + else + pedgetable = &edgetables[5]; + + return; + } + else + { + edgetableindex = 1; + } + } + + if (r_p0[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[8]; + else + pedgetable = &edgetables[9]; + + return; + } + else if (r_p1[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[10]; + else + pedgetable = &edgetables[11]; + + return; + } + + if (r_p0[1] > r_p2[1]) + edgetableindex += 2; + + if (r_p1[1] > r_p2[1]) + edgetableindex += 4; + + pedgetable = &edgetables[edgetableindex]; +} + + +#if 0 + +void D_PolysetRecursiveDrawLine (int *lp1, int *lp2) +{ + int d; + int new[6]; + int ofs; + + d = lp2[0] - lp1[0]; + if (d < -1 || d > 1) + goto split; + d = lp2[1] - lp1[1]; + if (d < -1 || d > 1) + goto split; + + return; // line is completed + +split: +// split this edge + new[0] = (lp1[0] + lp2[0]) >> 1; + new[1] = (lp1[1] + lp2[1]) >> 1; + new[5] = (lp1[5] + lp2[5]) >> 1; + new[2] = (lp1[2] + lp2[2]) >> 1; + new[3] = (lp1[3] + lp2[3]) >> 1; + new[4] = (lp1[4] + lp2[4]) >> 1; + +// draw the point + ofs = d_scantable[new[1]] + new[0]; + if (new[5] > d_pzbuffer[ofs]) + { + int pix; + + d_pzbuffer[ofs] = new[5]; + pix = skintable[new[3]>>16][new[2]>>16]; +// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)]; + d_viewbuffer[ofs] = pix; + } + +// recursively continue + D_PolysetRecursiveDrawLine (lp1, new); + D_PolysetRecursiveDrawLine (new, lp2); +} + +void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3) +{ + int d; + int new[4]; + + d = lp2[0] - lp1[0]; + if (d < -1 || d > 1) + goto split; + d = lp2[1] - lp1[1]; + if (d < -1 || d > 1) + goto split; + return; + +split: +// split this edge + new[0] = (lp1[0] + lp2[0]) >> 1; + new[1] = (lp1[1] + lp2[1]) >> 1; + new[5] = (lp1[5] + lp2[5]) >> 1; + new[2] = (lp1[2] + lp2[2]) >> 1; + new[3] = (lp1[3] + lp2[3]) >> 1; + new[4] = (lp1[4] + lp2[4]) >> 1; + + D_PolysetRecursiveDrawLine (new, lp3); + +// recursively continue + D_PolysetRecursiveTriangle (lp1, new, lp3); + D_PolysetRecursiveTriangle (new, lp2, lp3); +} + +#endif + diff --git a/WinQuake/d_scan.c b/WinQuake/d_scan.c index 008c783..11863ba 100644 --- a/WinQuake/d_scan.c +++ b/WinQuake/d_scan.c @@ -1,449 +1,449 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_scan.c -// -// Portable C scan-level rasterization code, all pixel depths. - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - -unsigned char *r_turb_pbase, *r_turb_pdest; -fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; -int *r_turb_turb; -int r_turb_spancount; - -void D_DrawTurbulent8Span (void); - - -/* -============= -D_WarpScreen - -// this performs a slight compression of the screen at the same time as -// the sine warp, to keep the edges from wrapping -============= -*/ -void D_WarpScreen (void) -{ - int w, h; - int u,v; - byte *dest; - int *turb; - int *col; - byte **row; - byte *rowptr[MAXHEIGHT+(AMP2*2)]; - int column[MAXWIDTH+(AMP2*2)]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float)scr_vrect.width; - hratio = h / (float)scr_vrect.height; - - for (v=0 ; v>16)&(CYCLE-1)])>>16)&63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; - *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb); - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); -} - -#endif // !id386 - - -/* -============= -Turbulent8 -============= -*/ -void Turbulent8 (espan_t *pspan) -{ - int count; - fixed16_t snext, tnext; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz16stepu, tdivz16stepu, zi16stepu; - - r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1)); - - r_turb_sstep = 0; // keep compiler happy - r_turb_tstep = 0; // ditto - - r_turb_pbase = (unsigned char *)cacheblock; - - sdivz16stepu = d_sdivzstepu * 16; - tdivz16stepu = d_tdivzstepu * 16; - zi16stepu = d_zistepu * 16; - - do - { - r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float)pspan->u; - dv = (float)pspan->v; - - sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; - tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; - zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - r_turb_s = (int)(sdivz * z) + sadjust; - if (r_turb_s > bbextents) - r_turb_s = bbextents; - else if (r_turb_s < 0) - r_turb_s = 0; - - r_turb_t = (int)(tdivz * z) + tadjust; - if (r_turb_t > bbextentt) - r_turb_t = bbextentt; - else if (r_turb_t < 0) - r_turb_t = 0; - - do - { - // calculate s and t at the far end of the span - if (count >= 16) - r_turb_spancount = 16; - else - r_turb_spancount = count; - - count -= r_turb_spancount; - - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz16stepu; - tdivz += tdivz16stepu; - zi += zi16stepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 16) - snext = 16; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 16) - tnext = 16; // guard against round-off error on <0 steps - - r_turb_sstep = (snext - r_turb_s) >> 4; - r_turb_tstep = (tnext - r_turb_t) >> 4; - } - else - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so - // can't step off polygon), clamp, calculate s and t steps across - // span by division, biasing steps low so we don't run off the - // texture - spancountminus1 = (float)(r_turb_spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * spancountminus1; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 16) - snext = 16; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 16) - tnext = 16; // guard against round-off error on <0 steps - - if (r_turb_spancount > 1) - { - r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); - r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); - } - } - - r_turb_s = r_turb_s & ((CYCLE<<16)-1); - r_turb_t = r_turb_t & ((CYCLE<<16)-1); - - D_DrawTurbulent8Span (); - - r_turb_s = snext; - r_turb_t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} - - -#if !id386 - -/* -============= -D_DrawSpans8 -============= -*/ -void D_DrawSpans8 (espan_t *pspan) -{ - int count, spancount; - unsigned char *pbase, *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (unsigned char *)cacheblock; - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8; - - do - { - pdest = (unsigned char *)((byte *)d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float)pspan->u; - dv = (float)pspan->v; - - sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; - tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; - zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - s = (int)(sdivz * z) + sadjust; - if (s > bbextents) - s = bbextents; - else if (s < 0) - s = 0; - - t = (int)(tdivz * z) + tadjust; - if (t > bbextentt) - t = bbextentt; - else if (t < 0) - t = 0; - - do - { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } - else - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so - // can't step off polygon), clamp, calculate s and t steps across - // span by division, biasing steps low so we don't run off the - // texture - spancountminus1 = (float)(spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * spancountminus1; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on <0 steps - - if (spancount > 1) - { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do - { - *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} - -#endif - - -#if !id386 - -/* -============= -D_DrawZSpans -============= -*/ -void D_DrawZSpans (espan_t *pspan) -{ - int count, doublecount, izistep; - int izi; - short *pdest; - unsigned ltemp; - double zi; - float du, dv; - -// FIXME: check for clamping/range problems -// we count on FP exceptions being turned off to avoid range problems - izistep = (int)(d_zistepu * 0x8000 * 0x10000); - - do - { - pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - // calculate the initial 1/z - du = (float)pspan->u; - dv = (float)pspan->v; - - zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; - // we count on FP exceptions being turned off to avoid range problems - izi = (int)(zi * 0x8000 * 0x10000); - - if ((long)pdest & 0x02) - { - *pdest++ = (short)(izi >> 16); - izi += izistep; - count--; - } - - if ((doublecount = count >> 1) > 0) - { - do - { - ltemp = izi >> 16; - izi += izistep; - ltemp |= izi & 0xFFFF0000; - izi += izistep; - *(int *)pdest = ltemp; - pdest += 2; - } while (--doublecount > 0); - } - - if (count & 1) - *pdest = (short)(izi >> 16); - - } while ((pspan = pspan->pnext) != NULL); -} - -#endif - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_scan.c +// +// Portable C scan-level rasterization code, all pixel depths. + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" + +unsigned char *r_turb_pbase, *r_turb_pdest; +fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; +int *r_turb_turb; +int r_turb_spancount; + +void D_DrawTurbulent8Span (void); + + +/* +============= +D_WarpScreen + +// this performs a slight compression of the screen at the same time as +// the sine warp, to keep the edges from wrapping +============= +*/ +void D_WarpScreen (void) +{ + int w, h; + int u,v; + byte *dest; + int *turb; + int *col; + byte **row; + byte *rowptr[MAXHEIGHT+(AMP2*2)]; + int column[MAXWIDTH+(AMP2*2)]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float)scr_vrect.width; + hratio = h / (float)scr_vrect.height; + + for (v=0 ; v>16)&(CYCLE-1)])>>16)&63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; + *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb); + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); +} + +#endif // !id386 + + +/* +============= +Turbulent8 +============= +*/ +void Turbulent8 (espan_t *pspan) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz16stepu, tdivz16stepu, zi16stepu; + + r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1)); + + r_turb_sstep = 0; // keep compiler happy + r_turb_tstep = 0; // ditto + + r_turb_pbase = (unsigned char *)cacheblock; + + sdivz16stepu = d_sdivzstepu * 16; + tdivz16stepu = d_tdivzstepu * 16; + zi16stepu = d_zistepu * 16; + + do + { + r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + + (screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + r_turb_s = (int)(sdivz * z) + sadjust; + if (r_turb_s > bbextents) + r_turb_s = bbextents; + else if (r_turb_s < 0) + r_turb_s = 0; + + r_turb_t = (int)(tdivz * z) + tadjust; + if (r_turb_t > bbextentt) + r_turb_t = bbextentt; + else if (r_turb_t < 0) + r_turb_t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 16) + r_turb_spancount = 16; + else + r_turb_spancount = count; + + count -= r_turb_spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz16stepu; + tdivz += tdivz16stepu; + zi += zi16stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + r_turb_sstep = (snext - r_turb_s) >> 4; + r_turb_tstep = (tnext - r_turb_t) >> 4; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(r_turb_spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + if (r_turb_spancount > 1) + { + r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); + r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); + } + } + + r_turb_s = r_turb_s & ((CYCLE<<16)-1); + r_turb_t = r_turb_t & ((CYCLE<<16)-1); + + D_DrawTurbulent8Span (); + + r_turb_s = snext; + r_turb_t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + + +#if !id386 + +/* +============= +D_DrawSpans8 +============= +*/ +void D_DrawSpans8 (espan_t *pspan) +{ + int count, spancount; + unsigned char *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (unsigned char *)cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + + do + { + pdest = (unsigned char *)((byte *)d_viewbuffer + + (screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do + { + *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + +#endif + + +#if !id386 + +/* +============= +D_DrawZSpans +============= +*/ +void D_DrawZSpans (espan_t *pspan) +{ + int count, doublecount, izistep; + int izi; + short *pdest; + unsigned ltemp; + double zi; + float du, dv; + +// FIXME: check for clamping/range problems +// we count on FP exceptions being turned off to avoid range problems + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial 1/z + du = (float)pspan->u; + dv = (float)pspan->v; + + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + // we count on FP exceptions being turned off to avoid range problems + izi = (int)(zi * 0x8000 * 0x10000); + + if ((long)pdest & 0x02) + { + *pdest++ = (short)(izi >> 16); + izi += izistep; + count--; + } + + if ((doublecount = count >> 1) > 0) + { + do + { + ltemp = izi >> 16; + izi += izistep; + ltemp |= izi & 0xFFFF0000; + izi += izistep; + *(int *)pdest = ltemp; + pdest += 2; + } while (--doublecount > 0); + } + + if (count & 1) + *pdest = (short)(izi >> 16); + + } while ((pspan = pspan->pnext) != NULL); +} + +#endif + diff --git a/WinQuake/d_scana.s b/WinQuake/d_scana.s index bd4fd74..3f4b91d 100644 --- a/WinQuake/d_scana.s +++ b/WinQuake/d_scana.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_scana.s // x86 assembly-language turbulent texture mapping code diff --git a/WinQuake/d_sky.c b/WinQuake/d_sky.c index 2f77d93..6007b6a 100644 --- a/WinQuake/d_sky.c +++ b/WinQuake/d_sky.c @@ -1,138 +1,138 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_sky.c - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - -#define SKY_SPAN_SHIFT 5 -#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) - - -/* -================= -D_Sky_uv_To_st -================= -*/ -void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) -{ - float wu, wv, temp; - vec3_t end; - - if (r_refdef.vrect.width >= r_refdef.vrect.height) - temp = (float)r_refdef.vrect.width; - else - temp = (float)r_refdef.vrect.height; - - wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp; - wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp; - - end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0]; - end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1]; - end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2]; - end[2] *= 3; - VectorNormalize (end); - - temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there - *s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000); - *t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000); -} - - -/* -================= -D_DrawSkyScans8 -================= -*/ -void D_DrawSkyScans8 (espan_t *pspan) -{ - int count, spancount, u, v; - unsigned char *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - do - { - pdest = (unsigned char *)((byte *)d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do - { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) - { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } - else - { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float)(spancount - 1); - - if (spancountminus1 > 0) - { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do - { - *pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) + - ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_sky.c + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" + +#define SKY_SPAN_SHIFT 5 +#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) + + +/* +================= +D_Sky_uv_To_st +================= +*/ +void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) +{ + float wu, wv, temp; + vec3_t end; + + if (r_refdef.vrect.width >= r_refdef.vrect.height) + temp = (float)r_refdef.vrect.width; + else + temp = (float)r_refdef.vrect.height; + + wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp; + wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp; + + end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0]; + end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1]; + end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2]; + end[2] *= 3; + VectorNormalize (end); + + temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there + *s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000); + *t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000); +} + + +/* +================= +D_DrawSkyScans8 +================= +*/ +void D_DrawSkyScans8 (espan_t *pspan) +{ + int count, spancount, u, v; + unsigned char *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + do + { + pdest = (unsigned char *)((byte *)d_viewbuffer + + (screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do + { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) + { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } + else + { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float)(spancount - 1); + + if (spancountminus1 > 0) + { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do + { + *pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) + + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + diff --git a/WinQuake/d_spr8.s b/WinQuake/d_spr8.s index a8d9845..42ccb62 100644 --- a/WinQuake/d_spr8.s +++ b/WinQuake/d_spr8.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_spr8.s // x86 assembly-language horizontal 8-bpp transparent span-drawing code. diff --git a/WinQuake/d_sprite.c b/WinQuake/d_sprite.c index 2f02ad2..7adff96 100644 --- a/WinQuake/d_sprite.c +++ b/WinQuake/d_sprite.c @@ -1,442 +1,442 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_sprite.c: software top-level rasterization driver module for drawing -// sprites - -#include "quakedef.h" -#include "d_local.h" - -static int sprite_height; -static int minindex, maxindex; -static sspan_t *sprite_spans; - -#if !id386 - -/* -===================== -D_SpriteDrawSpans -===================== -*/ -void D_SpriteDrawSpans (sspan_t *pspan) -{ - int count, spancount, izistep; - int izi; - byte *pbase, *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = cacheblock; - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8; - -// we count on FP exceptions being turned off to avoid range problems - izistep = (int)(d_zistepu * 0x8000 * 0x10000); - - do - { - pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u; - pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float)pspan->u; - dv = (float)pspan->v; - - sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; - tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; - zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - // we count on FP exceptions being turned off to avoid range problems - izi = (int)(zi * 0x8000 * 0x10000); - - s = (int)(sdivz * z) + sadjust; - if (s > bbextents) - s = bbextents; - else if (s < 0) - s = 0; - - t = (int)(tdivz * z) + tadjust; - if (t > bbextentt) - t = bbextentt; - else if (t < 0) - t = 0; - - do - { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } - else - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so - // can't step off polygon), clamp, calculate s and t steps across - // span by division, biasing steps low so we don't run off the - // texture - spancountminus1 = (float)(spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * spancountminus1; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - snext = (int)(sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int)(tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on <0 steps - - if (spancount > 1) - { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do - { - btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); - if (btemp != 255) - { - if (*pz <= (izi >> 16)) - { - *pz = izi >> 16; - *pdest = btemp; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); -} - -#endif - - -/* -===================== -D_SpriteScanLeftEdge -===================== -*/ -void D_SpriteScanLeftEdge (void) -{ - int i, v, itop, ibottom, lmaxindex; - emitpoint_t *pvert, *pnext; - sspan_t *pspan; - float du, dv, vtop, vbottom, slope; - fixed16_t u, u_step; - - pspan = sprite_spans; - i = minindex; - if (i == 0) - i = r_spritedesc.nump; - - lmaxindex = maxindex; - if (lmaxindex == 0) - lmaxindex = r_spritedesc.nump; - - vtop = ceil (r_spritedesc.pverts[i].v); - - do - { - pvert = &r_spritedesc.pverts[i]; - pnext = pvert - 1; - - vbottom = ceil (pnext->v); - - if (vtop < vbottom) - { - du = pnext->u - pvert->u; - dv = pnext->v - pvert->v; - slope = du / dv; - u_step = (int)(slope * 0x10000); - // adjust u to ceil the integer portion - u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + - (0x10000 - 1); - itop = (int)vtop; - ibottom = (int)vbottom; - - for (v=itop ; vu = u >> 16; - pspan->v = v; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - - i--; - if (i == 0) - i = r_spritedesc.nump; - - } while (i != lmaxindex); -} - - -/* -===================== -D_SpriteScanRightEdge -===================== -*/ -void D_SpriteScanRightEdge (void) -{ - int i, v, itop, ibottom; - emitpoint_t *pvert, *pnext; - sspan_t *pspan; - float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; - fixed16_t u, u_step; - - pspan = sprite_spans; - i = minindex; - - vvert = r_spritedesc.pverts[i].v; - if (vvert < r_refdef.fvrecty_adj) - vvert = r_refdef.fvrecty_adj; - if (vvert > r_refdef.fvrectbottom_adj) - vvert = r_refdef.fvrectbottom_adj; - - vtop = ceil (vvert); - - do - { - pvert = &r_spritedesc.pverts[i]; - pnext = pvert + 1; - - vnext = pnext->v; - if (vnext < r_refdef.fvrecty_adj) - vnext = r_refdef.fvrecty_adj; - if (vnext > r_refdef.fvrectbottom_adj) - vnext = r_refdef.fvrectbottom_adj; - - vbottom = ceil (vnext); - - if (vtop < vbottom) - { - uvert = pvert->u; - if (uvert < r_refdef.fvrectx_adj) - uvert = r_refdef.fvrectx_adj; - if (uvert > r_refdef.fvrectright_adj) - uvert = r_refdef.fvrectright_adj; - - unext = pnext->u; - if (unext < r_refdef.fvrectx_adj) - unext = r_refdef.fvrectx_adj; - if (unext > r_refdef.fvrectright_adj) - unext = r_refdef.fvrectright_adj; - - du = unext - uvert; - dv = vnext - vvert; - slope = du / dv; - u_step = (int)(slope * 0x10000); - // adjust u to ceil the integer portion - u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + - (0x10000 - 1); - itop = (int)vtop; - ibottom = (int)vbottom; - - for (v=itop ; vcount = (u >> 16) - pspan->u; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - vvert = vnext; - - i++; - if (i == r_spritedesc.nump) - i = 0; - - } while (i != maxindex); - - pspan->count = DS_SPAN_LIST_END; // mark the end of the span list -} - - -/* -===================== -D_SpriteCalculateGradients -===================== -*/ -void D_SpriteCalculateGradients (void) -{ - vec3_t p_normal, p_saxis, p_taxis, p_temp1; - float distinv; - - TransformVector (r_spritedesc.vpn, p_normal); - TransformVector (r_spritedesc.vright, p_saxis); - TransformVector (r_spritedesc.vup, p_taxis); - VectorInverse (p_taxis); - - distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)); - - d_sdivzstepu = p_saxis[0] * xscaleinv; - d_tdivzstepu = p_taxis[0] * xscaleinv; - - d_sdivzstepv = -p_saxis[1] * yscaleinv; - d_tdivzstepv = -p_taxis[1] * yscaleinv; - - d_zistepu = p_normal[0] * xscaleinv * distinv; - d_zistepv = -p_normal[1] * yscaleinv * distinv; - - d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - - ycenter * d_sdivzstepv; - d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - - ycenter * d_tdivzstepv; - d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - - ycenter * d_zistepv; - - TransformVector (modelorg, p_temp1); - - sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - - (-(cachewidth >> 1) << 16); - tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - - (-(sprite_height >> 1) << 16); - -// -1 (-epsilon) so we never wander off the edge of the texture - bbextents = (cachewidth << 16) - 1; - bbextentt = (sprite_height << 16) - 1; -} - - -/* -===================== -D_DrawSprite -===================== -*/ -void D_DrawSprite (void) -{ - int i, nump; - float ymin, ymax; - emitpoint_t *pverts; - sspan_t spans[MAXHEIGHT+1]; - - sprite_spans = spans; - -// find the top and bottom vertices, and make sure there's at least one scan to -// draw - ymin = 999999.9; - ymax = -999999.9; - pverts = r_spritedesc.pverts; - - for (i=0 ; iv < ymin) - { - ymin = pverts->v; - minindex = i; - } - - if (pverts->v > ymax) - { - ymax = pverts->v; - maxindex = i; - } - - pverts++; - } - - ymin = ceil (ymin); - ymax = ceil (ymax); - - if (ymin >= ymax) - return; // doesn't cross any scans at all - - cachewidth = r_spritedesc.pspriteframe->width; - sprite_height = r_spritedesc.pspriteframe->height; - cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0]; - -// copy the first vertex to the last vertex, so we don't have to deal with -// wrapping - nump = r_spritedesc.nump; - pverts = r_spritedesc.pverts; - pverts[nump] = pverts[0]; - - D_SpriteCalculateGradients (); - D_SpriteScanLeftEdge (); - D_SpriteScanRightEdge (); - D_SpriteDrawSpans (sprite_spans); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_sprite.c: software top-level rasterization driver module for drawing +// sprites + +#include "quakedef.h" +#include "d_local.h" + +static int sprite_height; +static int minindex, maxindex; +static sspan_t *sprite_spans; + +#if !id386 + +/* +===================== +D_SpriteDrawSpans +===================== +*/ +void D_SpriteDrawSpans (sspan_t *pspan) +{ + int count, spancount, izistep; + int izi; + byte *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + +// we count on FP exceptions being turned off to avoid range problems + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + // we count on FP exceptions being turned off to avoid range problems + izi = (int)(zi * 0x8000 * 0x10000); + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do + { + btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + if (btemp != 255) + { + if (*pz <= (izi >> 16)) + { + *pz = izi >> 16; + *pdest = btemp; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); +} + +#endif + + +/* +===================== +D_SpriteScanLeftEdge +===================== +*/ +void D_SpriteScanLeftEdge (void) +{ + int i, v, itop, ibottom, lmaxindex; + emitpoint_t *pvert, *pnext; + sspan_t *pspan; + float du, dv, vtop, vbottom, slope; + fixed16_t u, u_step; + + pspan = sprite_spans; + i = minindex; + if (i == 0) + i = r_spritedesc.nump; + + lmaxindex = maxindex; + if (lmaxindex == 0) + lmaxindex = r_spritedesc.nump; + + vtop = ceil (r_spritedesc.pverts[i].v); + + do + { + pvert = &r_spritedesc.pverts[i]; + pnext = pvert - 1; + + vbottom = ceil (pnext->v); + + if (vtop < vbottom) + { + du = pnext->u - pvert->u; + dv = pnext->v - pvert->v; + slope = du / dv; + u_step = (int)(slope * 0x10000); + // adjust u to ceil the integer portion + u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + + (0x10000 - 1); + itop = (int)vtop; + ibottom = (int)vbottom; + + for (v=itop ; vu = u >> 16; + pspan->v = v; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + + i--; + if (i == 0) + i = r_spritedesc.nump; + + } while (i != lmaxindex); +} + + +/* +===================== +D_SpriteScanRightEdge +===================== +*/ +void D_SpriteScanRightEdge (void) +{ + int i, v, itop, ibottom; + emitpoint_t *pvert, *pnext; + sspan_t *pspan; + float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; + fixed16_t u, u_step; + + pspan = sprite_spans; + i = minindex; + + vvert = r_spritedesc.pverts[i].v; + if (vvert < r_refdef.fvrecty_adj) + vvert = r_refdef.fvrecty_adj; + if (vvert > r_refdef.fvrectbottom_adj) + vvert = r_refdef.fvrectbottom_adj; + + vtop = ceil (vvert); + + do + { + pvert = &r_spritedesc.pverts[i]; + pnext = pvert + 1; + + vnext = pnext->v; + if (vnext < r_refdef.fvrecty_adj) + vnext = r_refdef.fvrecty_adj; + if (vnext > r_refdef.fvrectbottom_adj) + vnext = r_refdef.fvrectbottom_adj; + + vbottom = ceil (vnext); + + if (vtop < vbottom) + { + uvert = pvert->u; + if (uvert < r_refdef.fvrectx_adj) + uvert = r_refdef.fvrectx_adj; + if (uvert > r_refdef.fvrectright_adj) + uvert = r_refdef.fvrectright_adj; + + unext = pnext->u; + if (unext < r_refdef.fvrectx_adj) + unext = r_refdef.fvrectx_adj; + if (unext > r_refdef.fvrectright_adj) + unext = r_refdef.fvrectright_adj; + + du = unext - uvert; + dv = vnext - vvert; + slope = du / dv; + u_step = (int)(slope * 0x10000); + // adjust u to ceil the integer portion + u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + + (0x10000 - 1); + itop = (int)vtop; + ibottom = (int)vbottom; + + for (v=itop ; vcount = (u >> 16) - pspan->u; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + vvert = vnext; + + i++; + if (i == r_spritedesc.nump) + i = 0; + + } while (i != maxindex); + + pspan->count = DS_SPAN_LIST_END; // mark the end of the span list +} + + +/* +===================== +D_SpriteCalculateGradients +===================== +*/ +void D_SpriteCalculateGradients (void) +{ + vec3_t p_normal, p_saxis, p_taxis, p_temp1; + float distinv; + + TransformVector (r_spritedesc.vpn, p_normal); + TransformVector (r_spritedesc.vright, p_saxis); + TransformVector (r_spritedesc.vup, p_taxis); + VectorInverse (p_taxis); + + distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)); + + d_sdivzstepu = p_saxis[0] * xscaleinv; + d_tdivzstepu = p_taxis[0] * xscaleinv; + + d_sdivzstepv = -p_saxis[1] * yscaleinv; + d_tdivzstepv = -p_taxis[1] * yscaleinv; + + d_zistepu = p_normal[0] * xscaleinv * distinv; + d_zistepv = -p_normal[1] * yscaleinv * distinv; + + d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - + ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - + ycenter * d_tdivzstepv; + d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - + ycenter * d_zistepv; + + TransformVector (modelorg, p_temp1); + + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + (-(cachewidth >> 1) << 16); + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + (-(sprite_height >> 1) << 16); + +// -1 (-epsilon) so we never wander off the edge of the texture + bbextents = (cachewidth << 16) - 1; + bbextentt = (sprite_height << 16) - 1; +} + + +/* +===================== +D_DrawSprite +===================== +*/ +void D_DrawSprite (void) +{ + int i, nump; + float ymin, ymax; + emitpoint_t *pverts; + sspan_t spans[MAXHEIGHT+1]; + + sprite_spans = spans; + +// find the top and bottom vertices, and make sure there's at least one scan to +// draw + ymin = 999999.9; + ymax = -999999.9; + pverts = r_spritedesc.pverts; + + for (i=0 ; iv < ymin) + { + ymin = pverts->v; + minindex = i; + } + + if (pverts->v > ymax) + { + ymax = pverts->v; + maxindex = i; + } + + pverts++; + } + + ymin = ceil (ymin); + ymax = ceil (ymax); + + if (ymin >= ymax) + return; // doesn't cross any scans at all + + cachewidth = r_spritedesc.pspriteframe->width; + sprite_height = r_spritedesc.pspriteframe->height; + cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0]; + +// copy the first vertex to the last vertex, so we don't have to deal with +// wrapping + nump = r_spritedesc.nump; + pverts = r_spritedesc.pverts; + pverts[nump] = pverts[0]; + + D_SpriteCalculateGradients (); + D_SpriteScanLeftEdge (); + D_SpriteScanRightEdge (); + D_SpriteDrawSpans (sprite_spans); +} + diff --git a/WinQuake/d_surf.c b/WinQuake/d_surf.c index b09c5f8..ac3d844 100644 --- a/WinQuake/d_surf.c +++ b/WinQuake/d_surf.c @@ -1,335 +1,335 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_surf.c: rasterization driver surface heap manager - -#include "quakedef.h" -#include "d_local.h" -#include "r_local.h" - -float surfscale; -qboolean r_cache_thrash; // set if surface cache is thrashing - -int sc_size; -surfcache_t *sc_rover, *sc_base; - -#define GUARDSIZE 4 - - -int D_SurfaceCacheForRes (int width, int height) -{ - int size, pix; - - if (COM_CheckParm ("-surfcachesize")) - { - size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024; - return size; - } - - size = SURFCACHE_SIZE_AT_320X200; - - pix = width*height; - if (pix > 64000) - size += (pix-64000)*3; - - - return size; -} - -void D_CheckCacheGuard (void) -{ - byte *s; - int i; - - s = (byte *)sc_base + sc_size; - for (i=0 ; inext = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; - - D_ClearCacheGuard (); -} - - -/* -================== -D_FlushCaches -================== -*/ -void D_FlushCaches (void) -{ - surfcache_t *c; - - if (!sc_base) - return; - - for (c = sc_base ; c ; c = c->next) - { - if (c->owner) - *c->owner = NULL; - } - - sc_rover = sc_base; - sc_base->next = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; -} - -/* -================= -D_SCAlloc -================= -*/ -surfcache_t *D_SCAlloc (int width, int size) -{ - surfcache_t *new; - qboolean wrapped_this_time; - - if ((width < 0) || (width > 256)) - Sys_Error ("D_SCAlloc: bad cache width %d\n", width); - - if ((size <= 0) || (size > 0x10000)) - Sys_Error ("D_SCAlloc: bad cache size %d\n", size); - - size = (int)&((surfcache_t *)0)->data[size]; - size = (size + 3) & ~3; - if (size > sc_size) - Sys_Error ("D_SCAlloc: %i > cache size",size); - -// if there is not size bytes after the rover, reset to the start - wrapped_this_time = false; - - if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) - { - if (sc_rover) - { - wrapped_this_time = true; - } - sc_rover = sc_base; - } - -// colect and free surfcache_t blocks until the rover block is large enough - new = sc_rover; - if (sc_rover->owner) - *sc_rover->owner = NULL; - - while (new->size < size) - { - // free another - sc_rover = sc_rover->next; - if (!sc_rover) - Sys_Error ("D_SCAlloc: hit the end of memory"); - if (sc_rover->owner) - *sc_rover->owner = NULL; - - new->size += sc_rover->size; - new->next = sc_rover->next; - } - -// create a fragment out of any leftovers - if (new->size - size > 256) - { - sc_rover = (surfcache_t *)( (byte *)new + size); - sc_rover->size = new->size - size; - sc_rover->next = new->next; - sc_rover->width = 0; - sc_rover->owner = NULL; - new->next = sc_rover; - new->size = size; - } - else - sc_rover = new->next; - - new->width = width; -// DEBUG - if (width > 0) - new->height = (size - sizeof(*new) + sizeof(new->data)) / width; - - new->owner = NULL; // should be set properly after return - - if (d_roverwrapped) - { - if (wrapped_this_time || (sc_rover >= d_initial_rover)) - r_cache_thrash = true; - } - else if (wrapped_this_time) - { - d_roverwrapped = true; - } - -D_CheckCacheGuard (); // DEBUG - return new; -} - - -/* -================= -D_SCDump -================= -*/ -void D_SCDump (void) -{ - surfcache_t *test; - - for (test = sc_base ; test ; test = test->next) - { - if (test == sc_rover) - Sys_Printf ("ROVER:\n"); - printf ("%p : %i bytes %i width\n",test, test->size, test->width); - } -} - -//============================================================================= - -// if the num is not a power of 2, assume it will not repeat - -int MaskForNum (int num) -{ - if (num==128) - return 127; - if (num==64) - return 63; - if (num==32) - return 31; - if (num==16) - return 15; - return 255; -} - -int D_log2 (int num) -{ - int c; - - c = 0; - - while (num>>=1) - c++; - return c; -} - -//============================================================================= - -/* -================ -D_CacheSurface -================ -*/ -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) -{ - surfcache_t *cache; - -// -// if the surface is animating or flashing, flush the cache -// - r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture); - r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; - r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; - r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; - r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; - -// -// see if the cache holds apropriate data -// - cache = surface->cachespots[miplevel]; - - if (cache && !cache->dlight && surface->dlightframe != r_framecount - && cache->texture == r_drawsurf.texture - && cache->lightadj[0] == r_drawsurf.lightadj[0] - && cache->lightadj[1] == r_drawsurf.lightadj[1] - && cache->lightadj[2] == r_drawsurf.lightadj[2] - && cache->lightadj[3] == r_drawsurf.lightadj[3] ) - return cache; - -// -// determine shape of surface -// - surfscale = 1.0 / (1<extents[0] >> miplevel; - r_drawsurf.rowbytes = r_drawsurf.surfwidth; - r_drawsurf.surfheight = surface->extents[1] >> miplevel; - -// -// allocate memory if needed -// - if (!cache) // if a texture just animated, don't reallocate it - { - cache = D_SCAlloc (r_drawsurf.surfwidth, - r_drawsurf.surfwidth * r_drawsurf.surfheight); - surface->cachespots[miplevel] = cache; - cache->owner = &surface->cachespots[miplevel]; - cache->mipscale = surfscale; - } - - if (surface->dlightframe == r_framecount) - cache->dlight = 1; - else - cache->dlight = 0; - - r_drawsurf.surfdat = (pixel_t *)cache->data; - - cache->texture = r_drawsurf.texture; - cache->lightadj[0] = r_drawsurf.lightadj[0]; - cache->lightadj[1] = r_drawsurf.lightadj[1]; - cache->lightadj[2] = r_drawsurf.lightadj[2]; - cache->lightadj[3] = r_drawsurf.lightadj[3]; - -// -// draw and light the surface texture -// - r_drawsurf.surf = surface; - - c_surf++; - R_DrawSurface (); - - return surface->cachespots[miplevel]; -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_surf.c: rasterization driver surface heap manager + +#include "quakedef.h" +#include "d_local.h" +#include "r_local.h" + +float surfscale; +qboolean r_cache_thrash; // set if surface cache is thrashing + +int sc_size; +surfcache_t *sc_rover, *sc_base; + +#define GUARDSIZE 4 + + +int D_SurfaceCacheForRes (int width, int height) +{ + int size, pix; + + if (COM_CheckParm ("-surfcachesize")) + { + size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024; + return size; + } + + size = SURFCACHE_SIZE_AT_320X200; + + pix = width*height; + if (pix > 64000) + size += (pix-64000)*3; + + + return size; +} + +void D_CheckCacheGuard (void) +{ + byte *s; + int i; + + s = (byte *)sc_base + sc_size; + for (i=0 ; inext = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; + + D_ClearCacheGuard (); +} + + +/* +================== +D_FlushCaches +================== +*/ +void D_FlushCaches (void) +{ + surfcache_t *c; + + if (!sc_base) + return; + + for (c = sc_base ; c ; c = c->next) + { + if (c->owner) + *c->owner = NULL; + } + + sc_rover = sc_base; + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + +/* +================= +D_SCAlloc +================= +*/ +surfcache_t *D_SCAlloc (int width, int size) +{ + surfcache_t *new; + qboolean wrapped_this_time; + + if ((width < 0) || (width > 256)) + Sys_Error ("D_SCAlloc: bad cache width %d\n", width); + + if ((size <= 0) || (size > 0x10000)) + Sys_Error ("D_SCAlloc: bad cache size %d\n", size); + + size = (int)&((surfcache_t *)0)->data[size]; + size = (size + 3) & ~3; + if (size > sc_size) + Sys_Error ("D_SCAlloc: %i > cache size",size); + +// if there is not size bytes after the rover, reset to the start + wrapped_this_time = false; + + if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) + { + if (sc_rover) + { + wrapped_this_time = true; + } + sc_rover = sc_base; + } + +// colect and free surfcache_t blocks until the rover block is large enough + new = sc_rover; + if (sc_rover->owner) + *sc_rover->owner = NULL; + + while (new->size < size) + { + // free another + sc_rover = sc_rover->next; + if (!sc_rover) + Sys_Error ("D_SCAlloc: hit the end of memory"); + if (sc_rover->owner) + *sc_rover->owner = NULL; + + new->size += sc_rover->size; + new->next = sc_rover->next; + } + +// create a fragment out of any leftovers + if (new->size - size > 256) + { + sc_rover = (surfcache_t *)( (byte *)new + size); + sc_rover->size = new->size - size; + sc_rover->next = new->next; + sc_rover->width = 0; + sc_rover->owner = NULL; + new->next = sc_rover; + new->size = size; + } + else + sc_rover = new->next; + + new->width = width; +// DEBUG + if (width > 0) + new->height = (size - sizeof(*new) + sizeof(new->data)) / width; + + new->owner = NULL; // should be set properly after return + + if (d_roverwrapped) + { + if (wrapped_this_time || (sc_rover >= d_initial_rover)) + r_cache_thrash = true; + } + else if (wrapped_this_time) + { + d_roverwrapped = true; + } + +D_CheckCacheGuard (); // DEBUG + return new; +} + + +/* +================= +D_SCDump +================= +*/ +void D_SCDump (void) +{ + surfcache_t *test; + + for (test = sc_base ; test ; test = test->next) + { + if (test == sc_rover) + Sys_Printf ("ROVER:\n"); + printf ("%p : %i bytes %i width\n",test, test->size, test->width); + } +} + +//============================================================================= + +// if the num is not a power of 2, assume it will not repeat + +int MaskForNum (int num) +{ + if (num==128) + return 127; + if (num==64) + return 63; + if (num==32) + return 31; + if (num==16) + return 15; + return 255; +} + +int D_log2 (int num) +{ + int c; + + c = 0; + + while (num>>=1) + c++; + return c; +} + +//============================================================================= + +/* +================ +D_CacheSurface +================ +*/ +surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) +{ + surfcache_t *cache; + +// +// if the surface is animating or flashing, flush the cache +// + r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture); + r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; + r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; + r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; + r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; + +// +// see if the cache holds apropriate data +// + cache = surface->cachespots[miplevel]; + + if (cache && !cache->dlight && surface->dlightframe != r_framecount + && cache->texture == r_drawsurf.texture + && cache->lightadj[0] == r_drawsurf.lightadj[0] + && cache->lightadj[1] == r_drawsurf.lightadj[1] + && cache->lightadj[2] == r_drawsurf.lightadj[2] + && cache->lightadj[3] == r_drawsurf.lightadj[3] ) + return cache; + +// +// determine shape of surface +// + surfscale = 1.0 / (1<extents[0] >> miplevel; + r_drawsurf.rowbytes = r_drawsurf.surfwidth; + r_drawsurf.surfheight = surface->extents[1] >> miplevel; + +// +// allocate memory if needed +// + if (!cache) // if a texture just animated, don't reallocate it + { + cache = D_SCAlloc (r_drawsurf.surfwidth, + r_drawsurf.surfwidth * r_drawsurf.surfheight); + surface->cachespots[miplevel] = cache; + cache->owner = &surface->cachespots[miplevel]; + cache->mipscale = surfscale; + } + + if (surface->dlightframe == r_framecount) + cache->dlight = 1; + else + cache->dlight = 0; + + r_drawsurf.surfdat = (pixel_t *)cache->data; + + cache->texture = r_drawsurf.texture; + cache->lightadj[0] = r_drawsurf.lightadj[0]; + cache->lightadj[1] = r_drawsurf.lightadj[1]; + cache->lightadj[2] = r_drawsurf.lightadj[2]; + cache->lightadj[3] = r_drawsurf.lightadj[3]; + +// +// draw and light the surface texture +// + r_drawsurf.surf = surface; + + c_surf++; + R_DrawSurface (); + + return surface->cachespots[miplevel]; +} + + diff --git a/WinQuake/d_vars.c b/WinQuake/d_vars.c index 9c9805d..38dbf33 100644 --- a/WinQuake/d_vars.c +++ b/WinQuake/d_vars.c @@ -1,50 +1,50 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_vars.c: global refresh variables - -#if !id386 - -#include "quakedef.h" - -// all global and static refresh variables are collected in a contiguous block -// to avoid cache conflicts. - -//------------------------------------------------------- -// global refresh variables -//------------------------------------------------------- - -// FIXME: make into one big structure, like cl or sv -// FIXME: do separately for refresh engine and driver - -float d_sdivzstepu, d_tdivzstepu, d_zistepu; -float d_sdivzstepv, d_tdivzstepv, d_zistepv; -float d_sdivzorigin, d_tdivzorigin, d_ziorigin; - -fixed16_t sadjust, tadjust, bbextents, bbextentt; - -pixel_t *cacheblock; -int cachewidth; -pixel_t *d_viewbuffer; -short *d_pzbuffer; -unsigned int d_zrowbytes; -unsigned int d_zwidth; - -#endif // !id386 - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_vars.c: global refresh variables + +#if !id386 + +#include "quakedef.h" + +// all global and static refresh variables are collected in a contiguous block +// to avoid cache conflicts. + +//------------------------------------------------------- +// global refresh variables +//------------------------------------------------------- + +// FIXME: make into one big structure, like cl or sv +// FIXME: do separately for refresh engine and driver + +float d_sdivzstepu, d_tdivzstepu, d_zistepu; +float d_sdivzstepv, d_tdivzstepv, d_zistepv; +float d_sdivzorigin, d_tdivzorigin, d_ziorigin; + +fixed16_t sadjust, tadjust, bbextents, bbextentt; + +pixel_t *cacheblock; +int cachewidth; +pixel_t *d_viewbuffer; +short *d_pzbuffer; +unsigned int d_zrowbytes; +unsigned int d_zwidth; + +#endif // !id386 + diff --git a/WinQuake/d_varsa.s b/WinQuake/d_varsa.s index 537c6b4..76d67eb 100644 --- a/WinQuake/d_varsa.s +++ b/WinQuake/d_varsa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // d_varsa.s // diff --git a/WinQuake/d_zpoint.c b/WinQuake/d_zpoint.c index 909f250..4c38acf 100644 --- a/WinQuake/d_zpoint.c +++ b/WinQuake/d_zpoint.c @@ -1,47 +1,47 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// d_zpoint.c: software driver module for drawing z-buffered points - -#include "quakedef.h" -#include "d_local.h" - - -/* -===================== -D_DrawZPoint -===================== -*/ -void D_DrawZPoint (void) -{ - byte *pdest; - short *pz; - int izi; - - pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; - pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u; - izi = (int)(r_zpointdesc.zi * 0x8000); - - if (*pz <= izi) - { - *pz = izi; - *pdest = r_zpointdesc.color; - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// d_zpoint.c: software driver module for drawing z-buffered points + +#include "quakedef.h" +#include "d_local.h" + + +/* +===================== +D_DrawZPoint +===================== +*/ +void D_DrawZPoint (void) +{ + byte *pdest; + short *pz; + int izi; + + pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; + pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u; + izi = (int)(r_zpointdesc.zi * 0x8000); + + if (*pz <= izi) + { + *pz = izi; + *pdest = r_zpointdesc.color; + } +} + diff --git a/WinQuake/data/COMEXP.TXT b/WinQuake/data/COMEXP.TXT index 06bc4af..9965b0f 100644 --- a/WinQuake/data/COMEXP.TXT +++ b/WinQuake/data/COMEXP.TXT @@ -1,487 +1,487 @@ - COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE - - This Commercial Exploitation License Agreement for QUAKE -(the "Agreement") is between Id Software, Inc., a Texas -Corporation, (hereinafter "Id Software") and Licensee (as described -on the signature page hereof) and is made effective beginning on -the date of last signature hereto (the "Effective Date"). - - R E C I T A L S - - WHEREAS, Id Software is the owner and developer of the -computer software game entitled QUAKE; - - WHEREAS, Id Software desires to license certain -non-exclusive rights regarding QUAKE to Licensee; and - - WHEREAS, Licensee desires to receive a license for such -rights. - - T E R M S A N D C O N D I T I O N S - - NOW, THEREFORE, for and in consideration of the mutual -premises contained herein and for other good and valuable -consideration, the receipt and sufficiency of which is hereby -acknowledged, the undersigned parties do hereby agree as follows: - - 1. DEFINITIONS. As used in this Agreement, the parties -hereto agree the words set forth below shall have the specified -meanings: - - a. "Authorized Copy" shall mean one (1) copy of the - Subject Game actually purchased by Licensee from an - Id Software approved retailer; and - - b. "Subject Game" shall mean the full registered - version of QUAKE on a CD-ROM and shall not mean the - shareware or any other version. - - 2. GRANT OF RIGHTS. Id Software hereby grants to -Licensee and Licensee hereby accepts, subject to the provisions and -conditions hereof, a world-wide (except as otherwise provided -herein), non-exclusive, non-transferable, and non-assignable -license to: - - a. publicly display an Authorized Copy in exchange for - rental payment; - - b. run the Authorized Copy so that it will accept - network/modem connections in exchange for payments - from end-users who also must have actually purchased - an Authorized Copy; and - - c. otherwise commercially exploit an Authorized Copy, - except that Licensee shall not copy, reproduce, - manufacture or distribute the Authorized Copy. - - 3. RESERVATION OF RIGHTS AND PROHIBITIONS. Id Software -expressly reserves all rights not granted herein. Under no -circumstances shall Licensee copy, reproduce, manufacture or -distribute (free of charge or otherwise) the Authorized Copy or the -Subject Game. Licensee shall not reverse engineer, decompile, -disassemble, modify or alter the Authorized Copy. Licensee is not -receiving any rights hereunder regarding the Trademark or any -artwork, sound, music or other element of the Subject Game. - - 4. OWNERSHIP. Title to and all ownership rights in and -to the Subject Game, and the QUAKE Trademark (the "Trademark") and -the copyrights, trademarks, patents and other intellectual property -rights related thereto shall remain with Id Software which shall have -the exclusive right to protect the same by copyright or otherwise. -Licensee shall have no ownership rights in or to the Subject Game or -the Trademark and Licensee shall not own any intellectual property -rights regarding the Authorized Copy, including, without limitation, -the copyright regarding the Authorized Copy. Licensee acknowledges -that it only has a limited license to use the Authorized Copy, as -specified in that certain QUAKE Enduser License contained within the -Authorized Copy and as specified in this Agreement. - - 5. TERM AND TERMINATION. - - a. The term of this Agreement and the license granted -herein begins on the Effective Date and shall expire on a date one -(1) calendar year from the Effective Date. - - b. Either party may terminate this Agreement, for any -reason or no reason, on thirty (30) days written notice to the -other party. Termination will be effective on the thirtieth (30th) -day following delivery of the described notice. Notwithstanding -anything to the contrary herein, this Agreement shall immediately -terminate, without the requirement of any notice from Id Software -to Licensee, upon the occurrence of any of the following: (a) if -Licensee shall file a petition in bankruptcy or make an assignment -for the benefit of creditors, or if any bankruptcy proceeding or -assignment for benefit of creditors, shall be commenced against -Licensee and not be dismissed within sixty (60) days after the date -of its commencement; (b) the insolvency of Licensee; (c) the -cessation by Licensee of its business; or (d) the cessation by -Licensee, without the prior written consent of Id Software of the -distribution, manufacture, and sale responsibilities embodied -herein. Further, Id Software may elect to terminate this Agreement -upon the occurrence of any of the following: (1) if Licensee's -business operations are interrupted for forty (40) consecutive -calendar days; or (2) if each of two Id Software audit inspections -during any eighteen (18) month period demonstrates an -understatement by Licensee of Royalty payments due Id Software for -the six (6) month period immediately preceding each such inspection -of five percent (5%) or more. Upon the occurrence of such -terminating event, and the election of Id Software, if necessary, -to cause such termination, this Agreement and any and all rights -thereunder shall terminate without prejudice to any rights or -claims Id Software may have, and all rights hereunder shall -thereupon terminate, revert to and be vested in Id Software. - - 6. EFFECT OF TERMINATION OR EXPIRATION. Termination or -expiration of this Agreement, either by Id Software or -automatically, shall not create any liability against Id Software. -Upon expiration or earlier termination of this Agreement, Licensee -shall have no further right to exercise the rights licensed -hereunder or otherwise acquired in relation to this Agreement. - - 7. INDEMNIFICATION. Licensee hereby agrees to -indemnify, hold harmless and defend Id Software and Id Software's -predecessors, successors, assigns, officers, directors, -shareholders, employees, agents, representatives, licensees, -sublicensees, distributors, attorneys and accountants -(collectively, the "Id Related Parties") from and against any and -all damages, claims, losses, causes of action, liabilities, -lawsuits, judgments and expenses (including, without limitation, -reasonable attorneys' fees and expenses) arising from, relating to -or in connection with a breach of this Agreement by Licensee and -arising from, relating to or in connection with the Licensee's use -or non-use of the Authorized Copy (collectively, the "Claims"). Id -Software agrees to notify Licensee of any such Claims within a -reasonable time after Id Software learns of same. Licensee, at its -own expense, shall defend Id Software and the Id Related Parties -from any and all Claims. Id Software and the Id Related Parties -reserve the right to participate in any defense of the Claims with -counsel of their choice, and at their own expense. In the event -Licensee fails to provide a defense, then Licensee shall be -responsible for paying the attorneys' fees and expenses incurred by -Id Software and the Id Related Parties regarding the defense of the -Claims. Id Software and the Id Related Parties, as applicable, -agree to reasonably assist in the defense of the Claims. No -settlement by Licensee of any Claims shall be valid unless Licensee -receives the prior written consent of Id Software and the Id -Related Parties, as applicable, to any such settlement. - - 8. CONFIDENTIALITY. It is understood and agreed that -any proprietary information of Id Software that may from time to -time be made available or become known to Licensee is to be treated -as confidential, is to be used solely in connection with Licensee's -performance under this Agreement, and is to be disclosed only to -employees of Licensee who have a need for access. Such proprietary -information shall include, but not be limited to, trade secrets, -release information, financial information, personnel information, -and the like. Reasonable measures shall be taken by Licensee to -protect the confidentiality of Id Software's proprietary -information and any memoranda or papers containing proprietary -information of Id Software's that Licensee may receive are to be -returned to Id Software upon request. Licensee's obligations and -duties under this paragraph shall survive expiration or earlier -termination of this Agreement. Licensee shall obtain from its -employees an undertaking in a form which may be supplied by Id -Software, and which is subject to Id Software's prior written -approval, not to use or disclose to any third party any information -or knowledge concerning the business of Id Software which may be -communicated to such employees. - - 9. LIMITATION OF LIABILITY. ID SOFTWARE EXPRESSLY -DISCLAIMS ALL WARRANTIES NOT PROVIDED BY ID SOFTWARE HEREUNDER. -UNDER NO CIRCUMSTANCES SHALL ID SOFTWARE BE LIABLE TO LICENSEE FOR -ACTUAL, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES OR -ANY OTHER DAMAGES, WHETHER OR NOT ID SOFTWARE RECEIVES NOTICE OF -ANY SUCH DAMAGES. - - 10. COMPLIANCE WITH APPLICABLE LAWS. In performing -under this Agreement, Licensee agrees to comply with all applicable -laws, [including, without limitation, 22 U.S.C., 2778 and 22 -U.S.C. C.F.R. Parts 120-130 (1995)] regulations, ordinances and -statutes, including, but not limited to, the import/export laws and -regulations of the United States and its governmental and -regulatory agencies (including, without limitation, the Bureau of -Export Administration and the U.S. Department of Commerce) and all -applicable international treaties and laws. Further, Licensee -shall defend, indemnify and hold harmless Id Software from any and -all sales tax, tariffs and/or duties in connection with Licensee's -performance hereunder. - - 11. SPECIFIC UNDERTAKINGS BY LICENSEE. In addition to -the obligations of Licensee otherwise set forth in this Agreement, -during the term of this Agreement, and thereafter where specified, -Licensee agrees that: - - a. It will not attack the title of Id Software to the -Subject Game or the Trademark and any copyright, patent or -trademark or other intellectual property right related thereto and -it will not attack the validity of the license granted hereunder -during the term hereof or thereafter; and - - b. It will promptly inform Id Software of any -unauthorized use of the Authorized Copy, the Subject Game and the -Trademark and any portions thereof and reasonably assist Id -Software in the enforcement of any rights Id Software may have -against such unauthorized users. - - 12. FINANCIAL OBLIGATIONS AND ACCOUNTING. - - a. Payment of Royalties. Licensee agrees to pay Id -Software a royalty ("Royalty") at the rate of twelve and one-half -percent (12.5%) of Net Income. The term "Net Income" shall mean -all revenue received by Licensee from the commercial use of the -Authorized Copy, less only Licensee's actual, documented costs -relating directly to such use. A Royalty shall only be due for -those months in which Licensee's gross revenue from QUAKE -distribution exceeds U.S. Five Thousand Dollars ($5,000.00) and in -such months Licensee shall pay a full Royalty on all revenue -received. - - b. Rendition of Statements. Licensee shall account to -Id Software with regard to transactions hereunder within forty-five -(45) days following the conclusion of each calendar quarter. -Licensee hereby represents and warrants that such statements of -account to be prepared shall be true and correct. The accounts -shall show in summary form the appropriate calculations relating to -the computation of Royalties, if any. The statements shall also -show the gross revenue received by Licensee per month. The -Royalties payable to Id Software hereunder shall be remitted with -the particular statement indicating such amount to be due. All -statements hereunder shall be deemed rendered when deposited, -postage prepaid, in the United States mail, addressed to Id -Software at Id Software's address set forth on the signature page -hereof. - - c. Books of Account and Audits. Licensee shall keep -books of account relating to the commercial use of the Authorized -Copy on the basis of generally accepted accounting principles and -shall maintain such books of account for a period of at least two -(2) years after the expiration or earlier termination of this -Agreement; provided, however, that Licensee shall not be required -to keep such records longer than seven (7) years from their date of -origination. Id Software may, upon reasonable notice and at its -own expense, audit the applicable records at Licensee's office, in -order to verify statements rendered hereunder. Any such audit -shall take place during reasonable business hours and in such -manner so as not to interfere with Licensee's normal business -activities. Id Software agrees that such information inspected -and/or copied on behalf of Id Software hereunder shall be used only -for the purpose of determining the accuracy of the statements, and -shall be revealed only to such officers, directors, employees, -agents and/or representatives of Id Software as necessary to verify -the accuracy of the statements. If in an audit of Licensee's books -and records it is determined that there is a short fall of ten -percent (10%) or more in Royalties reported for any calendar -quarter, in addition to payment of such short fall and interest as -may be due, as provided herein, Licensee shall reimburse Id -Software for the full out-of-pocket costs of the audit including -reasonable travel costs and expenses; provided, however, that the -amount of reimbursement paid by Licensee shall not exceed U.S. -Fifteen Thousand Dollars ($15,000.00) for any audit. - - d. Payment of the Royalty. Licensee assumes all risks -associated with fluctuations in foreign currency exchange rates. -Licensee shall pay and agrees to pay all sums due Id Software in -United States Dollars. With respect to Royalties due for -commercial use outside the United States, other currencies shall be -exchanged at the expense of Licensee into United States Dollars -using the bid price quoted at the Citibank, N.A. of New York, New -York, for the purchase of United States Dollars at the close of -business on the last day of the calendar quarter during which any -amounts accrue. Payment of the Royalties shall be made in Dallas -County, Texas. - - e. Interest. If Id Software does not receive the -applicable Royalty payment on or before the due date of such -payment, Licensee agrees to pay and shall pay interest on Royalties -owed to Id Software from such date as specified in the following -sentence at a rate per annum equal to the Index Rate. For purposes -of clarification, the interest will begin to accrue on the first -(1st) day following the due date of the Royalty payment, unless the -Royalty payment is paid timely. The "Index Rate" shall be the -prime rate as published in The Wall Street Journal's "Money Rates" -table. If multiple prime rates are quoted in the table, then the -highest prime rate will be the Index Rate. In the event that the -prime rate is no longer published in the "Money Rates" table, then -Id Software will choose a substitute Index Rate which is based upon -comparable information. The applicable interest rate will be -determined and take effect on the first day of each month. - - NOTHING HEREIN SHALL BE CONSTRUED AS A REQUEST OR DEMAND BY -ID SOFTWARE OF INTEREST AT A RATE HIGHER THAN ALLOWED BY APPLICABLE -LAW. IT IS THE INTENT OF THE PARTIES HERETO THAT NO INTEREST BE -CHARGED HEREUNDER WHICH EXCEEDS THE MAXIMUM RATE ALLOWED BY -APPLICABLE LAW. IF THE RATE REFERENCED ABOVE EXCEEDS THE MAXIMUM -RATE ALLOWED BY APPLICABLE LAW, THEN THE INTEREST RATE MADE -APPLICABLE HEREIN SHALL BE THE MAXIMUM RATE ALLOWED BY APPLICABLE -LAW. - - 13. SUBLICENSE. Licensee shall not be entitled to -sublicense any of its rights under this Agreement. - - 14. GOODWILL. Licensee recognizes the great value of -the goodwill associated with the Subject Game and the Trademark, -and acknowledges that such goodwill, now existing and hereafter -created, exclusively belongs to Id Software and that the Trademark -has acquired a secondary meaning in the mind of the public. - - 15. REMEDIES. In the event of a breach of this -Agreement by Id Software, Licensee's sole remedy shall be to -terminate this Agreement. In the event of a breach by Licensee of -this Agreement, Id Software may pursue the remedies to which it is -entitled under applicable law, including, but not limited to, -termination of this Agreement. Licensee agrees that its failure to -comply with the terms of this Agreement upon expiration or earlier -termination hereof or Licensee's unauthorized use of the Authorized -Copy may result in immediate and irreparable damage to Id Software -for which there is no adequate remedy at law, and in the event of -such failure by Licensee, Id Software shall be entitled to -injunctive relief. Pursuit of any remedy by Id Software shall not -constitute a waiver of any other right or remedy of Id Software -under this Agreement or under applicable law. Termination of this -Agreement shall not be a pre-condition to Id Software pursuing its -other remedies for breach. - - 16. LICENSEE'S WARRANTIES. Licensee warrants and -represents that it has full legal rights to enter into this -Agreement and to perform its obligations hereunder and that it will -comply, at all times during the terms of this Agreement, with all -applicable laws, as set forth hereinabove. - - 17. BANKRUPTCY. If Licensee's liabilities exceed its -assets, or if Licensee becomes unable to pay its debts as they -become due or if Licensee files for voluntary bankruptcy, or is -placed in bankruptcy which is not dissolved or dismissed after -thirty (30) days from the petition filing date, or if Licensee -becomes insolvent, or makes an assignment for the benefit of its -creditors or an arrangement pursuant to any bankruptcy laws or if -Licensee discontinues its business or if a receiver is appointed -for its business, this Agreement shall automatically terminate, -without notice, and become null and void; provided, however, all -duties of Licensee upon termination or expiration of this Agreement -shall continue in full force and effect. - - 18. ENTIRE AGREEMENT AND ASSIGNMENT. This Agreement -constitutes the entire understanding between Licensee and Id -Software regarding the Subject Game. Each and every clause of this -Agreement is severable from the whole and shall survive unless the -entire Agreement is declared unenforceable. No prior or present -agreements or representations shall be binding upon any of the -parties hereto unless incorporated in this Agreement. No -modification or change in this Agreement shall be valid or binding -upon the parties unless in writing, executed by the parties to be -bound thereby. This Agreement shall bind and inure to the benefit -of Id Software, its successors and assigns, and Id Software may -assign its rights hereunder, in Id Software's sole discretion. -This Agreement is personal to Licensee, and Licensee shall not -sublicense, assign, transfer, convey nor franchise its rights -granted hereunder. - - 19. CHOICE OF LAW, VENUE AND SERVICE OF PROCESS. This -Agreement shall be construed in accordance with the laws of the -State of Texas and applicable U.S. federal law and all claims -and/or lawsuits in connection with this Agreement must be brought -in Dallas County, Texas. Licensee hereby agrees that service of -process by certified mail to the address set forth below, with -return receipt requested, shall constitute valid service of process -upon Licensee. If for any reason Licensee has moved or cannot be -validly served, then Licensee appoints the Secretary of State of -the state of Texas to accept service of process on Licensee's -behalf. - - 20. EXCUSED PERFORMANCE. Neither party shall be deemed -to be in default of any provision of this Agreement nor be liable -for any delay, failure in performance or interruption of service, -resulting directly or indirectly from acts of God, civil or -military authority, civil disturbance, military action, war, -strikes, other catastrophes or any other similar cause beyond its -reasonable control. Written notice to the non-affected party of any -such condition shall be given by the affected party within ten (10) -days of the event. - - 21. DELIVERY OF NOTICES, AND DELIVERY OF PAYMENTS. -Unless otherwise directed in writing by the parties, all notices -given hereunder and all payments made hereunder shall be sent to -the addresses set forth on the signature page hereof. All -notices, requests, consents and other communications under this -Agreement shall be in writing and shall be deemed to have been -delivered on the date personally delivered or on the date deposited -in the United States Postal Service, postage prepaid, by certified -mail, return receipt requested, or telegraphed and confirmed, or -delivered by electronic facsimile and confirmed. Any notice to Id -Software shall also be sent to its counsel: D. Wade Cloud, Jr., -Hiersche, Martens, Hayward, Drakeley & Urbach, P.C., 15303 Dallas -Parkway, Suite 700, LB 17, Dallas, Texas 75248. - - 22. NO PARTNERSHIP, ETC. This Agreement does not -constitute and shall not be construed as constituting a partnership -or joint venture between Id Software and Licensee. Neither party -shall have any right to obligate or bind the other party in any -manner whatsoever, and nothing herein contained shall give, or is -intended to give, any rights of any kind to any third persons. - - 23. COUNTERPARTS. This Agreement may be executed in -several counterparts, each of which will be deemed to be an -original, and each of which alone and all of which together, shall -constitute one and the same instrument, but in making proof of this -Agreement it shall not be necessary to produce or account for each -copy of any counterpart other than the counterpart signed by the -party against whom this Agreement is to be enforced. This -Agreement may be transmitted by facsimile, and it is the intent of -the parties for the facsimile of any autograph printed by a -receiving facsimile machine to be an original signature and for the -facsimile and any complete photocopy of the Agreement to be deemed -an original counterpart. - - 24. MEDIATION. If a dispute arises out of or relates to -this Agreement, or a breach of this Agreement, and if the dispute -cannot be settled through direct discussion, then the parties agree -to endeavor to settle the dispute in an amicable manner by -mediation, under the applicable provisions of Section 154.00 et -seq., Texas Civil Practices and Remedies Code, as supplemented by -the rules of the Association of Attorney Mediators. - - 25. SURVIVAL. The following provisions shall survive -the expiration or earlier termination of this Agreement: -paragraphs 4., 7., 8., and the audit rights of Id Software in -paragraph 12.c. - - 26. MISCELLANEOUS. - - a. All captions in this Agreement are intended solely -for the convenience of the parties, and none shall effect the -meaning or construction of any provision. - - b. The terms and conditions of this Agreement have been -negotiated fully and freely among the parties. Accordingly, the -preparation of this Agreement by counsel for a given party will not -be material to the construction hereof, and the terms of this -Agreement shall not be strictly construed against such party. - - By signing in the spaces provided below, the parties have -agreed to all of the terms and conditions set forth in this -Agreement. - - -AGREED: - -LICENSEE: - - -Signed:_______________________________ -Printed Name:_________________________ -Title:________________________________ -Address:______________________________ -______________________________________ -______________________________________ -Telephone #: _________________________ -Fax #:________________________________ -E-Mail Address:_______________________ -Date: ________________________________ - - -AGREED: - -ID SOFTWARE, INC. - - -Signed:_______________________________ -Printed Name:_________________________ -Title:________________________________ -Address:______________________________ -______________________________________ -______________________________________ -Telephone #: _________________________ -Fax #:________________________________ -E-Mail Address:_______________________ -Date: ________________________________ - - - -June 10, 1996 - - - -COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE -(DWC:dw:3406.0299:dwc\doc:5017) - - + COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE + + This Commercial Exploitation License Agreement for QUAKE +(the "Agreement") is between Id Software, Inc., a Texas +Corporation, (hereinafter "Id Software") and Licensee (as described +on the signature page hereof) and is made effective beginning on +the date of last signature hereto (the "Effective Date"). + + R E C I T A L S + + WHEREAS, Id Software is the owner and developer of the +computer software game entitled QUAKE; + + WHEREAS, Id Software desires to license certain +non-exclusive rights regarding QUAKE to Licensee; and + + WHEREAS, Licensee desires to receive a license for such +rights. + + T E R M S A N D C O N D I T I O N S + + NOW, THEREFORE, for and in consideration of the mutual +premises contained herein and for other good and valuable +consideration, the receipt and sufficiency of which is hereby +acknowledged, the undersigned parties do hereby agree as follows: + + 1. DEFINITIONS. As used in this Agreement, the parties +hereto agree the words set forth below shall have the specified +meanings: + + a. "Authorized Copy" shall mean one (1) copy of the + Subject Game actually purchased by Licensee from an + Id Software approved retailer; and + + b. "Subject Game" shall mean the full registered + version of QUAKE on a CD-ROM and shall not mean the + shareware or any other version. + + 2. GRANT OF RIGHTS. Id Software hereby grants to +Licensee and Licensee hereby accepts, subject to the provisions and +conditions hereof, a world-wide (except as otherwise provided +herein), non-exclusive, non-transferable, and non-assignable +license to: + + a. publicly display an Authorized Copy in exchange for + rental payment; + + b. run the Authorized Copy so that it will accept + network/modem connections in exchange for payments + from end-users who also must have actually purchased + an Authorized Copy; and + + c. otherwise commercially exploit an Authorized Copy, + except that Licensee shall not copy, reproduce, + manufacture or distribute the Authorized Copy. + + 3. RESERVATION OF RIGHTS AND PROHIBITIONS. Id Software +expressly reserves all rights not granted herein. Under no +circumstances shall Licensee copy, reproduce, manufacture or +distribute (free of charge or otherwise) the Authorized Copy or the +Subject Game. Licensee shall not reverse engineer, decompile, +disassemble, modify or alter the Authorized Copy. Licensee is not +receiving any rights hereunder regarding the Trademark or any +artwork, sound, music or other element of the Subject Game. + + 4. OWNERSHIP. Title to and all ownership rights in and +to the Subject Game, and the QUAKE Trademark (the "Trademark") and +the copyrights, trademarks, patents and other intellectual property +rights related thereto shall remain with Id Software which shall have +the exclusive right to protect the same by copyright or otherwise. +Licensee shall have no ownership rights in or to the Subject Game or +the Trademark and Licensee shall not own any intellectual property +rights regarding the Authorized Copy, including, without limitation, +the copyright regarding the Authorized Copy. Licensee acknowledges +that it only has a limited license to use the Authorized Copy, as +specified in that certain QUAKE Enduser License contained within the +Authorized Copy and as specified in this Agreement. + + 5. TERM AND TERMINATION. + + a. The term of this Agreement and the license granted +herein begins on the Effective Date and shall expire on a date one +(1) calendar year from the Effective Date. + + b. Either party may terminate this Agreement, for any +reason or no reason, on thirty (30) days written notice to the +other party. Termination will be effective on the thirtieth (30th) +day following delivery of the described notice. Notwithstanding +anything to the contrary herein, this Agreement shall immediately +terminate, without the requirement of any notice from Id Software +to Licensee, upon the occurrence of any of the following: (a) if +Licensee shall file a petition in bankruptcy or make an assignment +for the benefit of creditors, or if any bankruptcy proceeding or +assignment for benefit of creditors, shall be commenced against +Licensee and not be dismissed within sixty (60) days after the date +of its commencement; (b) the insolvency of Licensee; (c) the +cessation by Licensee of its business; or (d) the cessation by +Licensee, without the prior written consent of Id Software of the +distribution, manufacture, and sale responsibilities embodied +herein. Further, Id Software may elect to terminate this Agreement +upon the occurrence of any of the following: (1) if Licensee's +business operations are interrupted for forty (40) consecutive +calendar days; or (2) if each of two Id Software audit inspections +during any eighteen (18) month period demonstrates an +understatement by Licensee of Royalty payments due Id Software for +the six (6) month period immediately preceding each such inspection +of five percent (5%) or more. Upon the occurrence of such +terminating event, and the election of Id Software, if necessary, +to cause such termination, this Agreement and any and all rights +thereunder shall terminate without prejudice to any rights or +claims Id Software may have, and all rights hereunder shall +thereupon terminate, revert to and be vested in Id Software. + + 6. EFFECT OF TERMINATION OR EXPIRATION. Termination or +expiration of this Agreement, either by Id Software or +automatically, shall not create any liability against Id Software. +Upon expiration or earlier termination of this Agreement, Licensee +shall have no further right to exercise the rights licensed +hereunder or otherwise acquired in relation to this Agreement. + + 7. INDEMNIFICATION. Licensee hereby agrees to +indemnify, hold harmless and defend Id Software and Id Software's +predecessors, successors, assigns, officers, directors, +shareholders, employees, agents, representatives, licensees, +sublicensees, distributors, attorneys and accountants +(collectively, the "Id Related Parties") from and against any and +all damages, claims, losses, causes of action, liabilities, +lawsuits, judgments and expenses (including, without limitation, +reasonable attorneys' fees and expenses) arising from, relating to +or in connection with a breach of this Agreement by Licensee and +arising from, relating to or in connection with the Licensee's use +or non-use of the Authorized Copy (collectively, the "Claims"). Id +Software agrees to notify Licensee of any such Claims within a +reasonable time after Id Software learns of same. Licensee, at its +own expense, shall defend Id Software and the Id Related Parties +from any and all Claims. Id Software and the Id Related Parties +reserve the right to participate in any defense of the Claims with +counsel of their choice, and at their own expense. In the event +Licensee fails to provide a defense, then Licensee shall be +responsible for paying the attorneys' fees and expenses incurred by +Id Software and the Id Related Parties regarding the defense of the +Claims. Id Software and the Id Related Parties, as applicable, +agree to reasonably assist in the defense of the Claims. No +settlement by Licensee of any Claims shall be valid unless Licensee +receives the prior written consent of Id Software and the Id +Related Parties, as applicable, to any such settlement. + + 8. CONFIDENTIALITY. It is understood and agreed that +any proprietary information of Id Software that may from time to +time be made available or become known to Licensee is to be treated +as confidential, is to be used solely in connection with Licensee's +performance under this Agreement, and is to be disclosed only to +employees of Licensee who have a need for access. Such proprietary +information shall include, but not be limited to, trade secrets, +release information, financial information, personnel information, +and the like. Reasonable measures shall be taken by Licensee to +protect the confidentiality of Id Software's proprietary +information and any memoranda or papers containing proprietary +information of Id Software's that Licensee may receive are to be +returned to Id Software upon request. Licensee's obligations and +duties under this paragraph shall survive expiration or earlier +termination of this Agreement. Licensee shall obtain from its +employees an undertaking in a form which may be supplied by Id +Software, and which is subject to Id Software's prior written +approval, not to use or disclose to any third party any information +or knowledge concerning the business of Id Software which may be +communicated to such employees. + + 9. LIMITATION OF LIABILITY. ID SOFTWARE EXPRESSLY +DISCLAIMS ALL WARRANTIES NOT PROVIDED BY ID SOFTWARE HEREUNDER. +UNDER NO CIRCUMSTANCES SHALL ID SOFTWARE BE LIABLE TO LICENSEE FOR +ACTUAL, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES OR +ANY OTHER DAMAGES, WHETHER OR NOT ID SOFTWARE RECEIVES NOTICE OF +ANY SUCH DAMAGES. + + 10. COMPLIANCE WITH APPLICABLE LAWS. In performing +under this Agreement, Licensee agrees to comply with all applicable +laws, [including, without limitation, 22 U.S.C., 2778 and 22 +U.S.C. C.F.R. Parts 120-130 (1995)] regulations, ordinances and +statutes, including, but not limited to, the import/export laws and +regulations of the United States and its governmental and +regulatory agencies (including, without limitation, the Bureau of +Export Administration and the U.S. Department of Commerce) and all +applicable international treaties and laws. Further, Licensee +shall defend, indemnify and hold harmless Id Software from any and +all sales tax, tariffs and/or duties in connection with Licensee's +performance hereunder. + + 11. SPECIFIC UNDERTAKINGS BY LICENSEE. In addition to +the obligations of Licensee otherwise set forth in this Agreement, +during the term of this Agreement, and thereafter where specified, +Licensee agrees that: + + a. It will not attack the title of Id Software to the +Subject Game or the Trademark and any copyright, patent or +trademark or other intellectual property right related thereto and +it will not attack the validity of the license granted hereunder +during the term hereof or thereafter; and + + b. It will promptly inform Id Software of any +unauthorized use of the Authorized Copy, the Subject Game and the +Trademark and any portions thereof and reasonably assist Id +Software in the enforcement of any rights Id Software may have +against such unauthorized users. + + 12. FINANCIAL OBLIGATIONS AND ACCOUNTING. + + a. Payment of Royalties. Licensee agrees to pay Id +Software a royalty ("Royalty") at the rate of twelve and one-half +percent (12.5%) of Net Income. The term "Net Income" shall mean +all revenue received by Licensee from the commercial use of the +Authorized Copy, less only Licensee's actual, documented costs +relating directly to such use. A Royalty shall only be due for +those months in which Licensee's gross revenue from QUAKE +distribution exceeds U.S. Five Thousand Dollars ($5,000.00) and in +such months Licensee shall pay a full Royalty on all revenue +received. + + b. Rendition of Statements. Licensee shall account to +Id Software with regard to transactions hereunder within forty-five +(45) days following the conclusion of each calendar quarter. +Licensee hereby represents and warrants that such statements of +account to be prepared shall be true and correct. The accounts +shall show in summary form the appropriate calculations relating to +the computation of Royalties, if any. The statements shall also +show the gross revenue received by Licensee per month. The +Royalties payable to Id Software hereunder shall be remitted with +the particular statement indicating such amount to be due. All +statements hereunder shall be deemed rendered when deposited, +postage prepaid, in the United States mail, addressed to Id +Software at Id Software's address set forth on the signature page +hereof. + + c. Books of Account and Audits. Licensee shall keep +books of account relating to the commercial use of the Authorized +Copy on the basis of generally accepted accounting principles and +shall maintain such books of account for a period of at least two +(2) years after the expiration or earlier termination of this +Agreement; provided, however, that Licensee shall not be required +to keep such records longer than seven (7) years from their date of +origination. Id Software may, upon reasonable notice and at its +own expense, audit the applicable records at Licensee's office, in +order to verify statements rendered hereunder. Any such audit +shall take place during reasonable business hours and in such +manner so as not to interfere with Licensee's normal business +activities. Id Software agrees that such information inspected +and/or copied on behalf of Id Software hereunder shall be used only +for the purpose of determining the accuracy of the statements, and +shall be revealed only to such officers, directors, employees, +agents and/or representatives of Id Software as necessary to verify +the accuracy of the statements. If in an audit of Licensee's books +and records it is determined that there is a short fall of ten +percent (10%) or more in Royalties reported for any calendar +quarter, in addition to payment of such short fall and interest as +may be due, as provided herein, Licensee shall reimburse Id +Software for the full out-of-pocket costs of the audit including +reasonable travel costs and expenses; provided, however, that the +amount of reimbursement paid by Licensee shall not exceed U.S. +Fifteen Thousand Dollars ($15,000.00) for any audit. + + d. Payment of the Royalty. Licensee assumes all risks +associated with fluctuations in foreign currency exchange rates. +Licensee shall pay and agrees to pay all sums due Id Software in +United States Dollars. With respect to Royalties due for +commercial use outside the United States, other currencies shall be +exchanged at the expense of Licensee into United States Dollars +using the bid price quoted at the Citibank, N.A. of New York, New +York, for the purchase of United States Dollars at the close of +business on the last day of the calendar quarter during which any +amounts accrue. Payment of the Royalties shall be made in Dallas +County, Texas. + + e. Interest. If Id Software does not receive the +applicable Royalty payment on or before the due date of such +payment, Licensee agrees to pay and shall pay interest on Royalties +owed to Id Software from such date as specified in the following +sentence at a rate per annum equal to the Index Rate. For purposes +of clarification, the interest will begin to accrue on the first +(1st) day following the due date of the Royalty payment, unless the +Royalty payment is paid timely. The "Index Rate" shall be the +prime rate as published in The Wall Street Journal's "Money Rates" +table. If multiple prime rates are quoted in the table, then the +highest prime rate will be the Index Rate. In the event that the +prime rate is no longer published in the "Money Rates" table, then +Id Software will choose a substitute Index Rate which is based upon +comparable information. The applicable interest rate will be +determined and take effect on the first day of each month. + + NOTHING HEREIN SHALL BE CONSTRUED AS A REQUEST OR DEMAND BY +ID SOFTWARE OF INTEREST AT A RATE HIGHER THAN ALLOWED BY APPLICABLE +LAW. IT IS THE INTENT OF THE PARTIES HERETO THAT NO INTEREST BE +CHARGED HEREUNDER WHICH EXCEEDS THE MAXIMUM RATE ALLOWED BY +APPLICABLE LAW. IF THE RATE REFERENCED ABOVE EXCEEDS THE MAXIMUM +RATE ALLOWED BY APPLICABLE LAW, THEN THE INTEREST RATE MADE +APPLICABLE HEREIN SHALL BE THE MAXIMUM RATE ALLOWED BY APPLICABLE +LAW. + + 13. SUBLICENSE. Licensee shall not be entitled to +sublicense any of its rights under this Agreement. + + 14. GOODWILL. Licensee recognizes the great value of +the goodwill associated with the Subject Game and the Trademark, +and acknowledges that such goodwill, now existing and hereafter +created, exclusively belongs to Id Software and that the Trademark +has acquired a secondary meaning in the mind of the public. + + 15. REMEDIES. In the event of a breach of this +Agreement by Id Software, Licensee's sole remedy shall be to +terminate this Agreement. In the event of a breach by Licensee of +this Agreement, Id Software may pursue the remedies to which it is +entitled under applicable law, including, but not limited to, +termination of this Agreement. Licensee agrees that its failure to +comply with the terms of this Agreement upon expiration or earlier +termination hereof or Licensee's unauthorized use of the Authorized +Copy may result in immediate and irreparable damage to Id Software +for which there is no adequate remedy at law, and in the event of +such failure by Licensee, Id Software shall be entitled to +injunctive relief. Pursuit of any remedy by Id Software shall not +constitute a waiver of any other right or remedy of Id Software +under this Agreement or under applicable law. Termination of this +Agreement shall not be a pre-condition to Id Software pursuing its +other remedies for breach. + + 16. LICENSEE'S WARRANTIES. Licensee warrants and +represents that it has full legal rights to enter into this +Agreement and to perform its obligations hereunder and that it will +comply, at all times during the terms of this Agreement, with all +applicable laws, as set forth hereinabove. + + 17. BANKRUPTCY. If Licensee's liabilities exceed its +assets, or if Licensee becomes unable to pay its debts as they +become due or if Licensee files for voluntary bankruptcy, or is +placed in bankruptcy which is not dissolved or dismissed after +thirty (30) days from the petition filing date, or if Licensee +becomes insolvent, or makes an assignment for the benefit of its +creditors or an arrangement pursuant to any bankruptcy laws or if +Licensee discontinues its business or if a receiver is appointed +for its business, this Agreement shall automatically terminate, +without notice, and become null and void; provided, however, all +duties of Licensee upon termination or expiration of this Agreement +shall continue in full force and effect. + + 18. ENTIRE AGREEMENT AND ASSIGNMENT. This Agreement +constitutes the entire understanding between Licensee and Id +Software regarding the Subject Game. Each and every clause of this +Agreement is severable from the whole and shall survive unless the +entire Agreement is declared unenforceable. No prior or present +agreements or representations shall be binding upon any of the +parties hereto unless incorporated in this Agreement. No +modification or change in this Agreement shall be valid or binding +upon the parties unless in writing, executed by the parties to be +bound thereby. This Agreement shall bind and inure to the benefit +of Id Software, its successors and assigns, and Id Software may +assign its rights hereunder, in Id Software's sole discretion. +This Agreement is personal to Licensee, and Licensee shall not +sublicense, assign, transfer, convey nor franchise its rights +granted hereunder. + + 19. CHOICE OF LAW, VENUE AND SERVICE OF PROCESS. This +Agreement shall be construed in accordance with the laws of the +State of Texas and applicable U.S. federal law and all claims +and/or lawsuits in connection with this Agreement must be brought +in Dallas County, Texas. Licensee hereby agrees that service of +process by certified mail to the address set forth below, with +return receipt requested, shall constitute valid service of process +upon Licensee. If for any reason Licensee has moved or cannot be +validly served, then Licensee appoints the Secretary of State of +the state of Texas to accept service of process on Licensee's +behalf. + + 20. EXCUSED PERFORMANCE. Neither party shall be deemed +to be in default of any provision of this Agreement nor be liable +for any delay, failure in performance or interruption of service, +resulting directly or indirectly from acts of God, civil or +military authority, civil disturbance, military action, war, +strikes, other catastrophes or any other similar cause beyond its +reasonable control. Written notice to the non-affected party of any +such condition shall be given by the affected party within ten (10) +days of the event. + + 21. DELIVERY OF NOTICES, AND DELIVERY OF PAYMENTS. +Unless otherwise directed in writing by the parties, all notices +given hereunder and all payments made hereunder shall be sent to +the addresses set forth on the signature page hereof. All +notices, requests, consents and other communications under this +Agreement shall be in writing and shall be deemed to have been +delivered on the date personally delivered or on the date deposited +in the United States Postal Service, postage prepaid, by certified +mail, return receipt requested, or telegraphed and confirmed, or +delivered by electronic facsimile and confirmed. Any notice to Id +Software shall also be sent to its counsel: D. Wade Cloud, Jr., +Hiersche, Martens, Hayward, Drakeley & Urbach, P.C., 15303 Dallas +Parkway, Suite 700, LB 17, Dallas, Texas 75248. + + 22. NO PARTNERSHIP, ETC. This Agreement does not +constitute and shall not be construed as constituting a partnership +or joint venture between Id Software and Licensee. Neither party +shall have any right to obligate or bind the other party in any +manner whatsoever, and nothing herein contained shall give, or is +intended to give, any rights of any kind to any third persons. + + 23. COUNTERPARTS. This Agreement may be executed in +several counterparts, each of which will be deemed to be an +original, and each of which alone and all of which together, shall +constitute one and the same instrument, but in making proof of this +Agreement it shall not be necessary to produce or account for each +copy of any counterpart other than the counterpart signed by the +party against whom this Agreement is to be enforced. This +Agreement may be transmitted by facsimile, and it is the intent of +the parties for the facsimile of any autograph printed by a +receiving facsimile machine to be an original signature and for the +facsimile and any complete photocopy of the Agreement to be deemed +an original counterpart. + + 24. MEDIATION. If a dispute arises out of or relates to +this Agreement, or a breach of this Agreement, and if the dispute +cannot be settled through direct discussion, then the parties agree +to endeavor to settle the dispute in an amicable manner by +mediation, under the applicable provisions of Section 154.00 et +seq., Texas Civil Practices and Remedies Code, as supplemented by +the rules of the Association of Attorney Mediators. + + 25. SURVIVAL. The following provisions shall survive +the expiration or earlier termination of this Agreement: +paragraphs 4., 7., 8., and the audit rights of Id Software in +paragraph 12.c. + + 26. MISCELLANEOUS. + + a. All captions in this Agreement are intended solely +for the convenience of the parties, and none shall effect the +meaning or construction of any provision. + + b. The terms and conditions of this Agreement have been +negotiated fully and freely among the parties. Accordingly, the +preparation of this Agreement by counsel for a given party will not +be material to the construction hereof, and the terms of this +Agreement shall not be strictly construed against such party. + + By signing in the spaces provided below, the parties have +agreed to all of the terms and conditions set forth in this +Agreement. + + +AGREED: + +LICENSEE: + + +Signed:_______________________________ +Printed Name:_________________________ +Title:________________________________ +Address:______________________________ +______________________________________ +______________________________________ +Telephone #: _________________________ +Fax #:________________________________ +E-Mail Address:_______________________ +Date: ________________________________ + + +AGREED: + +ID SOFTWARE, INC. + + +Signed:_______________________________ +Printed Name:_________________________ +Title:________________________________ +Address:______________________________ +______________________________________ +______________________________________ +Telephone #: _________________________ +Fax #:________________________________ +E-Mail Address:_______________________ +Date: ________________________________ + + + +June 10, 1996 + + + +COMMERCIAL EXPLOITATION LICENSE AGREEMENT FOR QUAKE +(DWC:dw:3406.0299:dwc\doc:5017) + + diff --git a/WinQuake/data/HELP.TXT b/WinQuake/data/HELP.TXT index ef79fbd..02cb2e5 100644 --- a/WinQuake/data/HELP.TXT +++ b/WinQuake/data/HELP.TXT @@ -1,119 +1,119 @@ -TECH SUPPORT -Any of the information listed below could change. Check the id software -Web Site, at www.idsoftware.com, for updates. - -A. Tech Support Options -id Software does charge for technical support, but we strive to offer -this service at the lowest cost possible. Because volume on the support -lines dictate costs, we periodically adjust our rates for Voice Tech -Support. Check our web site for current pricing. - -Paying for Voice or Automated Support -1 -- You can get Voice Support using a major credit card for a one-time -shot. The system asks for your credit card number and expiration date, -then pre-authorizes your credit card for the tech support call. You will -only be billed for the number of minutes actually used. - -2 -- You can assign yourself a rechargeable PIN account. The system prompts -you for your credit card information, and assigns you a PIN account number. -You can use the PIN to access Voice Support, Automated Support and the -Game Hints Line. Once your account runs out, you can charge it up again. - -3 -- You may also charge up a PIN account using the number 1 (900) call-2-id. -Then call back at 1(800)ID-GAMES (1(800)434-3627), and use your new PIN to -receive all the support and hints you wish. - -4 -- id Software's Game Hints Line is accessible either using a PIN account -via 1 (800) ID-GAMES (see above), or by calling 1 (900) CALL2-ID, which -places the call on your phone bill. - - 1. Voice Support - Telephone -- 1 (800) id-games - - Lines Open from 12 noon to 10pm Central Time, 7 Days a - week ($1.75 per minute). Closed some holidays - - Please have the following information handy. - 1. Game title and version number. (The version - number can be found on the end text screen.) - 2. Your operating system, processor, processor - speed and amount of RAM. - 3. If you are having a sound, video or modem - problem, we need to know the device brand name - and model. - - 2. Automated Support - Telephone -- 1 (800) id-games - - Lines Open 24 hours a day, 365 days a year, or 366 days - in Leap years ($0.25 per minute) - - Please have pencil and paper handy. - - 3. E-mail Support - Just send your e-mail to support@idsoftware.com - - We will do our best to respond within 48 hours after - receiving your e-mail. - - When sending e-mail, cut and paste the following into your - e-mail message and fill in the blanks: - -Date: -Name: -Phone number: -E-mail address: (please include this, we redirect tons of mail) -Game Title: -Version #: -Operating system (eg., DOS 6.0 or Windows 95): -Computer type: -Processor type: -Processor speed: -Video card brand and model: (only if video problem) -Audio card brand and model: (only if audio problem) -Modem brand and model: (only if modem problem) -Network card brand and model: (only if netgame problem) -Network configuration (eg., NET.CFG file): (only if netgame problem) -Drivers, protocol stacks, and versions: (eg., lsl v2.14, exp16odi -v2.33, and ipxodi v3.01) (only if netgame problem) -If there were any error messages or fault information, report them -here: -Please state the problem you encountered: -Please state how to reproduce the problem: - - 4. Web Support - Found at www.idsoftware.com - - Our web support pages provide the same information that's - available via Automated Support, except it's free! - - 5. News Sites - For information, FAQ, or announcements: - rec.games.computer.quake.announce - For editing and hecking Quake-related files: - rec.games.computer.quake.editing - For general Quake discussion: - rec.games.computer.quake.misc - - 6. Game Hints Line - Telephone -- 1 (800) id-games or 1 (900) call-2-id - - Lines Open 24 hours a day, 365 days a year, or 366 days - in Leap years ($0.85 per minute) - You must be 18 years of age or have parental permission - to call 1 (900) call-2-id. - -B. In Europe - The help lines in Europe are open 7:30am - 5:00pm GMT, - Monday - Friday. - -English: +44 01923 209145 -German: +44 (0)1923 209151 -French: +44 (0)1923 209148 - -C. Problems - If you have an unfavorable experience using our services, please - send e-mail to 911@idsoftware.com. We would also like to hear - from you if you have something positive to share with us. Kindly - include your full name, address, phone number, and the problem - encountered or information you'd like to tell us about. +TECH SUPPORT +Any of the information listed below could change. Check the id software +Web Site, at www.idsoftware.com, for updates. + +A. Tech Support Options +id Software does charge for technical support, but we strive to offer +this service at the lowest cost possible. Because volume on the support +lines dictate costs, we periodically adjust our rates for Voice Tech +Support. Check our web site for current pricing. + +Paying for Voice or Automated Support +1 -- You can get Voice Support using a major credit card for a one-time +shot. The system asks for your credit card number and expiration date, +then pre-authorizes your credit card for the tech support call. You will +only be billed for the number of minutes actually used. + +2 -- You can assign yourself a rechargeable PIN account. The system prompts +you for your credit card information, and assigns you a PIN account number. +You can use the PIN to access Voice Support, Automated Support and the +Game Hints Line. Once your account runs out, you can charge it up again. + +3 -- You may also charge up a PIN account using the number 1 (900) call-2-id. +Then call back at 1(800)ID-GAMES (1(800)434-3627), and use your new PIN to +receive all the support and hints you wish. + +4 -- id Software's Game Hints Line is accessible either using a PIN account +via 1 (800) ID-GAMES (see above), or by calling 1 (900) CALL2-ID, which +places the call on your phone bill. + + 1. Voice Support + Telephone -- 1 (800) id-games + + Lines Open from 12 noon to 10pm Central Time, 7 Days a + week ($1.75 per minute). Closed some holidays + + Please have the following information handy. + 1. Game title and version number. (The version + number can be found on the end text screen.) + 2. Your operating system, processor, processor + speed and amount of RAM. + 3. If you are having a sound, video or modem + problem, we need to know the device brand name + and model. + + 2. Automated Support + Telephone -- 1 (800) id-games + + Lines Open 24 hours a day, 365 days a year, or 366 days + in Leap years ($0.25 per minute) + + Please have pencil and paper handy. + + 3. E-mail Support + Just send your e-mail to support@idsoftware.com + + We will do our best to respond within 48 hours after + receiving your e-mail. + + When sending e-mail, cut and paste the following into your + e-mail message and fill in the blanks: + +Date: +Name: +Phone number: +E-mail address: (please include this, we redirect tons of mail) +Game Title: +Version #: +Operating system (eg., DOS 6.0 or Windows 95): +Computer type: +Processor type: +Processor speed: +Video card brand and model: (only if video problem) +Audio card brand and model: (only if audio problem) +Modem brand and model: (only if modem problem) +Network card brand and model: (only if netgame problem) +Network configuration (eg., NET.CFG file): (only if netgame problem) +Drivers, protocol stacks, and versions: (eg., lsl v2.14, exp16odi +v2.33, and ipxodi v3.01) (only if netgame problem) +If there were any error messages or fault information, report them +here: +Please state the problem you encountered: +Please state how to reproduce the problem: + + 4. Web Support + Found at www.idsoftware.com + + Our web support pages provide the same information that's + available via Automated Support, except it's free! + + 5. News Sites + For information, FAQ, or announcements: + rec.games.computer.quake.announce + For editing and hecking Quake-related files: + rec.games.computer.quake.editing + For general Quake discussion: + rec.games.computer.quake.misc + + 6. Game Hints Line + Telephone -- 1 (800) id-games or 1 (900) call-2-id + + Lines Open 24 hours a day, 365 days a year, or 366 days + in Leap years ($0.85 per minute) + You must be 18 years of age or have parental permission + to call 1 (900) call-2-id. + +B. In Europe + The help lines in Europe are open 7:30am - 5:00pm GMT, + Monday - Friday. + +English: +44 01923 209145 +German: +44 (0)1923 209151 +French: +44 (0)1923 209148 + +C. Problems + If you have an unfavorable experience using our services, please + send e-mail to 911@idsoftware.com. We would also like to hear + from you if you have something positive to share with us. Kindly + include your full name, address, phone number, and the problem + encountered or information you'd like to tell us about. diff --git a/WinQuake/data/LICINFO.TXT b/WinQuake/data/LICINFO.TXT index f909e38..17c5e51 100644 --- a/WinQuake/data/LICINFO.TXT +++ b/WinQuake/data/LICINFO.TXT @@ -1,97 +1,97 @@ -Here is a brief explanation of all the legal mumbo jumbo contained in the -various license agreements that may or may not be part of this package. - -(This document was designed to be a quick overview of our license terms. -You must refer to the full text of the license for a complete listing of -terms and conditions.) - -QUAKE SHAREWARE END USER LICENSE (slicnse.txt) or -What You Can and Cannot Do With the Shareware Version of Quake. - -CAN DO: --- Play & Enjoy the single player game --- Setup a shareware version based server on a not-for-profit basis - -CANNOT DO: --- Run the game with user developed levels. --- You may not commercially exploit the shareware version in any way - This specifically excludes retail distribution of the shareware - version. Do not call or e-mail to ask if you can be a retail - distributor of the shareware version -- the answer is no! --- Commercially exploit any id copyrighted and/or trademarked property. - Example: Game names, logos, graphics, etc. - - -QUAKE REGISTERED VERSION END USER LICENSE (rlicnse.txt) or -What You Can and Cannot Do With the Registered Version of Quake. - -CAN DO: --- Play & Enjoy the single player game --- Setup a registered version based server on a not-for-profit basis --- Develop new levels and/or level creation utilities. --- Play the game and/or setup a Registered Version based server using - a user-developed level. - -CANNOT DO: --- Commercially exploit the Registered Version of Quake in any way; - see commercially exploitation license info below. --- Commercially exploit any id copyrighted and/or trademarked - property. - Example: Game names, logos, game graphics, etc. --- Sell user-developed levels and/or tools - -COMMERCIAL EXPLOITATION LICENSE (comexp.txt -- accompanies Quake - registered version only) - -If you are interested in trying to make money using the registered version -of Quake (this sort of thing is not allowed using the shareware version) you -must sign our easy-to-digest Commercial Exploitation License. - -This is a royalty free license that allows you to run Quake for a profit -through a certain monthly gross profit range. If your Quake-related business -becomes successful the agreement brings id into the revenue stream. - -Basic terms of the commercial exploitation license: - --- License grants a royalty free commercial exploitation right for the - registered version of Quake as a whole so long as Quake's monthly gross - revenue is below $5,000.00 - --- License provides for a 12.5% royalty to be paid to id Software in months - where the licensee's Quake related monthly gross revenue is above $5,000.00 - --- Royalty is based off net income. Net income is defined as Quake-related - gross income less Quake-related expenses. - --- License expressly prohibits commercial exploitation via the sale (retail - or otherwise) of the shareware or registered versions of Quake. - --- License expressly prohibits advertising/marketing use of our copyrighted - and/or trademarked properties. - -To get into bed with us on this deal you must print two (2) copies of the -document named comexp.txt. (You should find comexp.txt somewhere on the -registered version CD.) Sign/fill in the blanks of both copies where -indicated and mail both to: - - id Software - 18601 LBJ #666 - Mesquite, TX 75150 - Attn: ComExp License - -We will then countersign the documents and mail one back to you. - -Two items worth noting here: - -1. It is VERY IMPORTANT that the information you enter in the signature -block be legible. We prefer it if you enter the info into the blanks before -printing your two copies. If we cannot read your information we will not be -able to return the documents to you. - -2. The terms of this document are not subject to negotiation. If you cannot -live with the terms spelled out in the agreement do not engage in any -commercial exploitation of Quake and do not sign the document. - - - - +Here is a brief explanation of all the legal mumbo jumbo contained in the +various license agreements that may or may not be part of this package. + +(This document was designed to be a quick overview of our license terms. +You must refer to the full text of the license for a complete listing of +terms and conditions.) + +QUAKE SHAREWARE END USER LICENSE (slicnse.txt) or +What You Can and Cannot Do With the Shareware Version of Quake. + +CAN DO: +-- Play & Enjoy the single player game +-- Setup a shareware version based server on a not-for-profit basis + +CANNOT DO: +-- Run the game with user developed levels. +-- You may not commercially exploit the shareware version in any way + This specifically excludes retail distribution of the shareware + version. Do not call or e-mail to ask if you can be a retail + distributor of the shareware version -- the answer is no! +-- Commercially exploit any id copyrighted and/or trademarked property. + Example: Game names, logos, graphics, etc. + + +QUAKE REGISTERED VERSION END USER LICENSE (rlicnse.txt) or +What You Can and Cannot Do With the Registered Version of Quake. + +CAN DO: +-- Play & Enjoy the single player game +-- Setup a registered version based server on a not-for-profit basis +-- Develop new levels and/or level creation utilities. +-- Play the game and/or setup a Registered Version based server using + a user-developed level. + +CANNOT DO: +-- Commercially exploit the Registered Version of Quake in any way; + see commercially exploitation license info below. +-- Commercially exploit any id copyrighted and/or trademarked + property. + Example: Game names, logos, game graphics, etc. +-- Sell user-developed levels and/or tools + +COMMERCIAL EXPLOITATION LICENSE (comexp.txt -- accompanies Quake + registered version only) + +If you are interested in trying to make money using the registered version +of Quake (this sort of thing is not allowed using the shareware version) you +must sign our easy-to-digest Commercial Exploitation License. + +This is a royalty free license that allows you to run Quake for a profit +through a certain monthly gross profit range. If your Quake-related business +becomes successful the agreement brings id into the revenue stream. + +Basic terms of the commercial exploitation license: + +-- License grants a royalty free commercial exploitation right for the + registered version of Quake as a whole so long as Quake's monthly gross + revenue is below $5,000.00 + +-- License provides for a 12.5% royalty to be paid to id Software in months + where the licensee's Quake related monthly gross revenue is above $5,000.00 + +-- Royalty is based off net income. Net income is defined as Quake-related + gross income less Quake-related expenses. + +-- License expressly prohibits commercial exploitation via the sale (retail + or otherwise) of the shareware or registered versions of Quake. + +-- License expressly prohibits advertising/marketing use of our copyrighted + and/or trademarked properties. + +To get into bed with us on this deal you must print two (2) copies of the +document named comexp.txt. (You should find comexp.txt somewhere on the +registered version CD.) Sign/fill in the blanks of both copies where +indicated and mail both to: + + id Software + 18601 LBJ #666 + Mesquite, TX 75150 + Attn: ComExp License + +We will then countersign the documents and mail one back to you. + +Two items worth noting here: + +1. It is VERY IMPORTANT that the information you enter in the signature +block be legible. We prefer it if you enter the info into the blanks before +printing your two copies. If we cannot read your information we will not be +able to return the documents to you. + +2. The terms of this document are not subject to negotiation. If you cannot +live with the terms spelled out in the agreement do not engage in any +commercial exploitation of Quake and do not sign the document. + + + + diff --git a/WinQuake/data/ORDER.TXT b/WinQuake/data/ORDER.TXT index fb4598d..97bf863 100644 --- a/WinQuake/data/ORDER.TXT +++ b/WinQuake/data/ORDER.TXT @@ -1,103 +1,103 @@ -ORDERING INFO - To order the full version of Quake (or any other id Software -product) in North America, call our fulfillment center at 1-800-idgames -(1-800-434-3627). Except as noted by our operators, you can expect -Airborne Express afternoon delivery. The price for the full version -of Quake (available on PC CDROM only) is $45, plus $5 shipping, for a -total of $50. Our fulfillment center accepts Visa, Mastercard, and -American Express. You can also fax, mail, or email your order using -the attached forms. The fax number is (317) 361-3710 and the email -address is idsoftware@stream.com. To prepay and order with a check -by mail, send your check and the order form to: - - id Software - P.O. Box 4500 - Crawfordsville, IN 47933 - - To see an electronic catalog of our software, tshirts, hint books, and - other merchandise available, check out the Shopping Maul section of our - website at www.idsoftware.com. - -INTERNATIONAL ORDERS -Quake is available worldwide as a full retail product. To find out -which local stores carry Quake and other id products, contact the -following international affiliates: - -Europe Australia -GT Interactive Software Roadshow New Media -1712 583791 (U.K.) 1 902 962000 - -Taiwan Singapore -U.S. Summit Corporation Summit Co. (Singapore) Pte. Ltd. -706-0660 273-9988 - -Malaysia Honk Kong -Summit Co. (Malaysia) Sdn Bhd Tsun Tsun Trading Company -757-2244 571-4231 - -Thailand Israel/Jordan/Lebanon/Egypt -U.S. Summit Corp. (Overseas) Mirage Mulimedia -374-3956 972 3 510 5764 - -If you are in a territory that cannot access 1(800)idgames, and you -wish to order our products directly, you must place your order in -writing to the fax, mail, or email addresses listed above under -ORDERING INFO. - -International phone orders will NOT be accepted. Unfortunately, due -to international shipping costs, all international orders are sent -out via US Mail. This means we cannot guarantee timeliness of delivery -due to customs and other delays inherent to international shipping -______________________________________________________________________ - ORDER FORM -- USE THIS FORM TO FAX , MAIL OR EMAIL YOUR ORDER. - -id Software Order Center Date ______________ -PO BOX 4500 Phone: 1800 id games -Crawfordsville, IN 47933 Fax: (317) 361-3710 - idsoftware@stream.com - - -Product List and Prices in U.S. Currency: (check items) - -Quake (CD ROM only) $45 ____ -The Ultimate DOOM (Mac version available – must specify) $25 ____ -DOOM II (Mac version available – must specify) $40 ____ -Master Levels for DOOM II (CD ROM only) $25 ____ -Final DOOM (CD ROM only) $40 ____ -DOOM Hint Book $15 ____ -Original DOOM Tshirt (S,M.L.XL) $13 ____ -The Ultimate DOOM Tshirt (XXL only) $13 ____ -Final DOOM Tshirt $13 ____ -Heretic:Shadow of the Serpent Riders (CD ROM only) $40 ____ -Heretic Hint Book $15 ____ -Hexen:Beyond Heretic (Mac version available – must specify) $40 ____ -Hexen:Deathkings of the Dark Citadel (CD ROM only) $25 ____ -Hexen Hint Book $15 ____ -Hexen Tshirt (XXL only) $13 ____ -Wolfenstein 3D (PC CD only) $20 ____ -Commander Keen (3.5 disk only) $15 ____ - - Order total: $______ - -Name: Age (optional): - -Form of payment (check, money order, or credit card): - -Credit card number: Expiration Date: - -Exact mailing address:______________________________________ - _______________________________________ - _______________________________________ - _______________________________________ - -Phone: Fax: Email: - -Shipping: US orders-$5.00 first product/$2.00 each additional -(allow 3-5 business days) - -International shipping for prepaid orders are via US Mail, and -we cannot guarantee the time it will take to arrive. - -*Prices subject to change - - +ORDERING INFO + To order the full version of Quake (or any other id Software +product) in North America, call our fulfillment center at 1-800-idgames +(1-800-434-3627). Except as noted by our operators, you can expect +Airborne Express afternoon delivery. The price for the full version +of Quake (available on PC CDROM only) is $45, plus $5 shipping, for a +total of $50. Our fulfillment center accepts Visa, Mastercard, and +American Express. You can also fax, mail, or email your order using +the attached forms. The fax number is (317) 361-3710 and the email +address is idsoftware@stream.com. To prepay and order with a check +by mail, send your check and the order form to: + + id Software + P.O. Box 4500 + Crawfordsville, IN 47933 + + To see an electronic catalog of our software, tshirts, hint books, and + other merchandise available, check out the Shopping Maul section of our + website at www.idsoftware.com. + +INTERNATIONAL ORDERS +Quake is available worldwide as a full retail product. To find out +which local stores carry Quake and other id products, contact the +following international affiliates: + +Europe Australia +GT Interactive Software Roadshow New Media +1712 583791 (U.K.) 1 902 962000 + +Taiwan Singapore +U.S. Summit Corporation Summit Co. (Singapore) Pte. Ltd. +706-0660 273-9988 + +Malaysia Honk Kong +Summit Co. (Malaysia) Sdn Bhd Tsun Tsun Trading Company +757-2244 571-4231 + +Thailand Israel/Jordan/Lebanon/Egypt +U.S. Summit Corp. (Overseas) Mirage Mulimedia +374-3956 972 3 510 5764 + +If you are in a territory that cannot access 1(800)idgames, and you +wish to order our products directly, you must place your order in +writing to the fax, mail, or email addresses listed above under +ORDERING INFO. + +International phone orders will NOT be accepted. Unfortunately, due +to international shipping costs, all international orders are sent +out via US Mail. This means we cannot guarantee timeliness of delivery +due to customs and other delays inherent to international shipping +______________________________________________________________________ + ORDER FORM -- USE THIS FORM TO FAX , MAIL OR EMAIL YOUR ORDER. + +id Software Order Center Date ______________ +PO BOX 4500 Phone: 1800 id games +Crawfordsville, IN 47933 Fax: (317) 361-3710 + idsoftware@stream.com + + +Product List and Prices in U.S. Currency: (check items) + +Quake (CD ROM only) $45 ____ +The Ultimate DOOM (Mac version available – must specify) $25 ____ +DOOM II (Mac version available – must specify) $40 ____ +Master Levels for DOOM II (CD ROM only) $25 ____ +Final DOOM (CD ROM only) $40 ____ +DOOM Hint Book $15 ____ +Original DOOM Tshirt (S,M.L.XL) $13 ____ +The Ultimate DOOM Tshirt (XXL only) $13 ____ +Final DOOM Tshirt $13 ____ +Heretic:Shadow of the Serpent Riders (CD ROM only) $40 ____ +Heretic Hint Book $15 ____ +Hexen:Beyond Heretic (Mac version available – must specify) $40 ____ +Hexen:Deathkings of the Dark Citadel (CD ROM only) $25 ____ +Hexen Hint Book $15 ____ +Hexen Tshirt (XXL only) $13 ____ +Wolfenstein 3D (PC CD only) $20 ____ +Commander Keen (3.5 disk only) $15 ____ + + Order total: $______ + +Name: Age (optional): + +Form of payment (check, money order, or credit card): + +Credit card number: Expiration Date: + +Exact mailing address:______________________________________ + _______________________________________ + _______________________________________ + _______________________________________ + +Phone: Fax: Email: + +Shipping: US orders-$5.00 first product/$2.00 each additional +(allow 3-5 business days) + +International shipping for prepaid orders are via US Mail, and +we cannot guarantee the time it will take to arrive. + +*Prices subject to change + + diff --git a/WinQuake/data/README.TXT b/WinQuake/data/README.TXT index fc62729..63549f5 100644 --- a/WinQuake/data/README.TXT +++ b/WinQuake/data/README.TXT @@ -1,456 +1,456 @@ -Welcome to Quake! - -This file details how to get Quake running on your system and what to do -if you have problems. We would like to thank Gandalf Technologies, Inc and -MPath Interactive for the use of their technology. We would also like to -thank Trent Reznor and Nine Inch Nails for their tremendous contributions -to Quake's entire audio portion. - -The NIN logo is a Registered Trademark licensed to Nothing Interactive, Inc. -All Rights Reserved. - -Quake System Requirements -------------------------- -IBM PC and Compatibles -Pentium processor or better -VGA Compatible Display or better -8MB RAM minimum, 16MB recommended (16 MB required for running under Win95) -CD-ROM drive Required -MS-DOS 5.0 or better or Windows 95 (does NOT run under Windows NT) -Hard Drive (30MB for Shareware, 80 MB for Registered) - -*** IMPORTANT!: Quake requires a floating point processor. -Systems that do not have an FPU installed will not run Quake -- at all. - -*** IMPORTANT Video Adapter Note! *** -On some ATI Mach32 cards, Quake can come up with a garbled video display. -This is due to a problem with the card in which 320x200 mode isn't -initialized correctly. Workarounds include: - -1) If running from Windows, start Quake from an icon, or from a windowed -(not fullscreen) MS-DOS prompt. If Quake is already running and has -the garbled screen, press Alt-Enter twice to switch to the desktop and -back to fullscreen, and the screen will display properly. - -2) If running from DOS, either put the line - -vid_mode 1 - -in id1\autoexec.cfg, or, typing blind, press tilde ('~') to bring down -the console, type - -vid_mode 1 - -and the screen will display properly. - -======================================================================== -Here are the text files included with the shareware release of Quake and -what they are: - -README.TXT This file -TECHINFO.TXT Technical information on Quake's subsystems and - their advanced use. -MANUAL.TXT Text version of the printed game manual -LICINFO.TXT Info on the various license files included with Quake -SLICNSE.TXT Shareware Quake end-user license -ORDER.TXT How to order Quake -HELP.TXT How to get help with Quake - -Here are the text files included with the registered version of Quake and -what they are: - -README.TXT This file -TECHINFO.TXT Technical information on Quake's subsystems and - their advanced use. -MANUAL.TXT Text version of the printed game manual -LICINFO.TXT Info on the various license files included with Quake -RLICNSE.TXT Registered Quake end-user license -COMEXP.TXT Commercial exploitation agreement -ORDER.TXT How to order Quake -HELP.TXT How to get help with Quake - - -Running Quake -------------- - -DOS: To launch Quake from the DOS Prompt, go to the Quake directory and -simply type "QUAKE" . (no quotes) - -Windows 95: To launch Quake in single player mode, double click on the file -QUAKE.EXE From Windows Explorer. To run Quake in Multi-Player mode using -the TCP/IP protocol, first check your network settings to ensure the -protocol is installed, then double click on the Q95.BAT file to launch the -game. In this version (v0.91) there is a minor bug that will cause the -Q95.BAT file to exit the first time you run it, without running Quake. -Merely double-click on that file again and it will work. - -Audio Setup ------------ - -When using a Sound Card with Quake, there are a few setup steps which must -be taken. First, the "BLASTER" environment variable setting must be in your -autoexec.bat (or you can type it in manually from the MS-DOS command prompt). -Running the Sound Blaster utility diagnose.exe will automatically configure -your sound card and put this statement in your autoexec.bat file for you. -A typical blaster setting looks like this (although yours may vary): - -SET BLASTER=A220 I5 D1 H5 P330 T6 - -If you want to play the audio track from the CD-ROM while playing Quake, -you must ensure that the audio cable from the CD-ROM is connected to the -sound card. - -If you think your sound card is setup properly and it STILL doesn't work, -check to make sure that your BLASTER environment variable contains the -high DMA setting (H5 in the above example). - -If you don't get sound while trying to play the audio track, check to see -if a small cable goes from the back of your CD-ROM player directly to your -sound card. If the CD-ROM audio cable is connected to your sound board (or -the motherboard in some cases) and you STILL don't hear CD Audio coming from -your speakers, make sure the MIXER program has the CD volume turned up. -You will also need to run the CD-ROM driver MSCDEX.EXE. Here is an example -of the files you should see (yours probably will vary) listed in your -CONFIG.SYS and AUTOEXEC.BAT (explanation is in parentheses): - -CONFIG.SYS: - -DEVICE=C:\PROSCSI\CDROM.SYS /D:PROCD01 (CD-ROM driver) - -AUTOEXEC.BAT: - -SET BLASTER=A220 I5 D1 H5 P330 T6 (sound environment variable setting) -C:\WINDOWS\COMMAND\MSCDEX.EXE /D:PROCD01 /L:D (CD-ROM driver) - -=================================================== -UltraSound MAX and UltraSound PnP Support for Quake -=================================================== - -Before running Quake, make sure that your sound card works and your -environment variables are set correctly. - -Other UltraSound Cards (ACE & Classic) --------------------------------------- -These drivers are not for the UltraSound ACE or UltraSound Classic -sound cards. We have heard mixed reports that MegaEm or SBOS -have a chance of working with the UltraSound Classic but there is a -short sound F/X delay. - -UltraSound PnP and PnP Pro --------------------------- -You must make sure that you do NOT have IWSBOS or MegaEm loaded. - -Setup ------ -Quake will automatically detect that the UltraSound Max or PnP -are installed. It does this by looking at the SET INTERWAVE (PnP) -and SET ULTRA16 (Max) environment variables. - -Quake will use the settings found on the SET ULTRASND/ULTRA16 (Max) -and in the IW.INI (PnP) file to determine what port settings to use. - -Troubleshooting Windows 95 (DOS Box) ------------------------------------- -We recommend that you restart your computer in MS-DOS Mode. DOS Box -may or may not work, so use at your own risk. - -CD Audio Input --------------- -If you have not already enabled CD audio output by default you will -need to enable it. For the UltraSound MAX you can run "ULTRINIT -EC". -For the UltraSound PnP you will need to enable the CD audio output -in Win'95 and then restart your computer into MS-DOS. - -=================================================== -Mouse Setup ------------ - -If you are going to use a mouse when playing Quake, you will need to load -your mouse driver. This should go in the AUTOEXEC.BAT file as well. Here -is an example: - -C:\LOGITECH\MOUSE\MOUSE.EXE (mouse driver) - - -Booting Clean -------------- - -If you are going to be running Quake with only 8 megabytes of RAM, it is best -to boot clean . You eliminate unwanted utilities or applications from taking -up valuable memory, without having to alter your regular AUTOEXEC.BAT and -CONFIG.SYS. Booting clean can be done in one of two ways. If you have -MS-DOS version 6.xx, booting clean is as simple a pressing the shift key -when you see the words "Starting MS-DOS". If you have MS-DOS ver 5.xx you -will need to make a system disk. - -To make a boot disk, type the following from the MS-DOS command prompt: - -FORMAT A: /S - -1. Make sure that this is a disk you wish to erase. -2. This disk absolutely HAS to be formatted in the A: drive. - -To use the system disk, place the disk in the A: drive and reset the -computer. - -NOTE: If your sound card requires a driver to be loaded, or you will be -using a mouse, or you will be using Quake's CD audio feature, the system -disk will need to have a CONFIG.SYS and AUTOEXEC.BAT that load the -appropriate drivers. - -Creating a Quake Shortcut - -As an alternative to making a Boot Disk, Windows 95 users can create a -Quake Shortcut. By double clicking onthis shortcut, Windows 95 will reboot -in MS-DOS mode and install only the desired drivers, giving you the same -results as using a Boot Disk. To create a Quake Shortcut, do the following: - -1. Using Explorer, right click and drag the file QUAKE.EXE, from the Quake - directory, to your desktop. Windows 95 will make an MS-DOS Icon titled - "Shortcut to quake". -2. Right click on the new icon, and from the menu that pops up, choose - "Properties". Then choose the "Program" tab at the top. -3. Now click on the "Advanced..." button near the bottom. The "Advanced - Program Settings" window should appear. -4. Select the "MS-DOS mode" check box and the "Specify a new MS-DOS - configuration" option button. -5. Now simply fill in the "CONFIG.SYS for MS-DOS mode:" and "AUTOEXEC.BAT - for MS-DOS mode:" boxes with the same sound, CD-ROM and mouse settings as - mentioned above in the Boot Disks section. -6. Click on "OK" when you are finished. If you wish, you can change your - Quake Shortcut Icon to something a little more exciting by clicking on - "Change Icon...". -7. To finish, click on "OK" again. - 8. You can rename your Quake Shortcut by right clicking on the shortcut - icon, choosing "Rename" and typing in the new name. - - -====================================================== -== Known Problems == -====================================================== - -Problem: Zombies sometime get stuck on the ground and connot get back up. -(You can still hear them, but you cannot kill them. This bug makes it -impossible to get 100% kills on whatever level it occurs on.) -Solution: There is no workaround for this bug. - -Problem: It is sometimes possible for the player to get stuck in a room or -in a wall. -Solution: If you get stuck, use the 'kill' console command. It is a good -idea to save your game often. - -Problem: View centering problems. Sometimes during a game, the view will not -center properly. The end result is the player view looking up torwards the -ceiling while walking. -Solution: Exit to the next level or use the 'kill' console command.. - - -====================================================== -== Troubleshooting == -====================================================== - -If Quake fails to start up, or has problems not addressed elsewhere in the -documentation, try the -safe command line switch, which disables a number -of parts of Quake that can be problems if there are hardware or configuration -problems. The -safe command line switch is equivalent to -stdvid, -nosound, --nonet, and -nocdaudio together. Those four switches do the following: - --stdvid: disables VESA video modes. - --nosound: disables sound card support. - --nonet: disables network card support. - --nocdaudio: disables CD audio support. - -If -safe makes the problem go away, try using each of the switches -individually to isolate the area in which you're experiencing the problem, -then either correct the configuration or hardware problem or play Quake with -that functionality disabled. - -If you still have problems, try booting clean in conjunction with -the -safe command line parameter. For information on booting clean, refer -to the "Booting Clean" section above. - -If you experience page faults while running Quarterdeck's QDPMI DPMI server, -this is caused by a bug in QDPMI. Workarounds: Remove QDPMI from CONFIG.SYS, -issue the command QDPMI OFF before running QUAKE, or get the update patch -for QDPMI from Quarterdeck. You may be running QDPMI without knowing it if -you have QEMM installed, because it can be installed as part of the QEMM -installation. - - -Technical Support ------------------ - -If you are having trouble installing or running Quake you can receive -technical support by sending e-mailing to support@idsoftware.com. You can -also refer to our web page, www.idsoftware.com, or call 1-800-idgames. - -When sending support e-mail, cut and paste the following into your e-mail -message and fill in the blanks: - -Date: -Name: -Phone number: -E-mail address: (please include this, we redirect tons of mail) -Game Title: -Version #: -Operating system (i.e., DOS 6.0 or Windows 95): -Computer type: -BIOS date: -BIOS version: -Processor type: -Processor speed: -Do you program at school/work? -Do you provide tech. support at school/work? -Please state the problem you encountered: -Please state how to reproduce the problem: - -If program crashed with nasty undecipherable techno-garbage, please -look for the eight-digit hex number which comes after "eip=" -and write it down here: - -** NOTE: If you are sending a bug report, PLEASE refer to the TECHINFO.TXT -file for the correct form and procedures. - - -====================================================== -== Version History == -====================================================== -v1.01 -- Bugs fixed ------------------------------------------------------- -* Fixed modem code -* Fixed fraglimit & timelimit -* Added NOEXIT cvar (so no one can exit a level) ------------------------------------------------------- -v1.00 -- Bugs fixed ------------------------------------------------------- -* Gravis Ultrasound audio support (still has bugs) -* More deathmatch start spots on E1M6 and END -* Print server version and PROG CRC on connect -* -dedicated starts start.map if nothing else specified -* fixed lookspring function during net game -* fixed rare crash during long running dedicated server ------------------------------------------------------- -v0.94 -- Bugs fixed / Features added -- LIMITED BETA VERSION ------------------------------------------------------- -* Totally rewritten menus -* New lighting model with overbrighting -* Parsed lowercase BLASTER parms -* Better Sound Blaster shutdown code -* Rewrote BLASTER initialization -* Fixed DMA channel 0 bugs -* Added SBPro 8 stereo setup -* Fix delayed sound on 8 bit Sound Blasters -* Fixed speed key affecting angle-turning from keyboard -* Fixed "no such Alias frame" bugs -* Fixed Zombie not getting up bug -* Checked for very high joystick values, signalling a failed read -* Unstuck jumping Fiends and Spawn -* Fixed large BModels blinking out in complex areas -* Fixed s_localsound with no sound started -* Saved spawn parms in savegame -* Fixed screenshot save location -* Bind with no arguments no longer clears value -* Allow console in intermission / finale -* Fixed false gib messages -* Full-screen TAB scoreboard in DeathMatch -* Fixed "+playdemo " from command line -* Trapped overflow in sizebuf messages -* Moveup / movedown in water! -* Fixed-up Talk command -* Added unsupported crosshair option ("crosshair 1" from console) -* Colored chat messages with notify sound -* Fixed "connect during intermission" bug -* Changelevel while demos running no longer crashes -* Fixed changelevel with no map left up loading screen -* Fixed long names entered from the console causing crash -* Stopped demos changing while in the menus - -* Fixed modem initialization from menu -* Fixed serial reliable stream getting stalled -* Serial/modem code fixes - 16550a lost transmit buffer empty interrupts - fixed sometimes processing interrupts from com1 when using com2 - added com3/com4 support from menus - fixed first character of modem init not getting sent - saved serial/modem settings in config.cfg -* Fixed name and colors not always sent to server at startup -* Fixed "stopdemo" crashing the system when there wasn't a demo playing -* Added server's TCP/IP and IPX addresses (if available) to status command - -* In 0.92, an additional check for a usable VESA video mode was added; -the numpages field was verified to be greater than 0, and no mode was -supported that had numpages set to 0 (which indicates that there's not -enough video memory for that mode). ATI's VESA driver, m64vbe, -reports 0 for numpages, so VESA video modes that were available in 0.91 -were no longer available in 0.92. This extra numpages check has -been removed. - ------------------------------------------------------------------------ -v0.93 -- Never officially released; internal testing only. ------------------------------------------------------------------------ -v0.92 -- Bugs fixed ------------------------------------------------------------------------ -Typing long strings in the hostname or modem init field in the menus caused -crashes. - -Under Win95 IPX was detected but not functional, resulting in the game -exiting to DOS. - -If -nosound, got "S_LocalSound: can't cache" on every keypress in the menu. - -When vid_nopageflip was set to 1 in VESA modes, going underwater resulted in -only the upper left corner of the drawing area being updated. - -The single player scoreboard (tab) printed text incorrectly in all modes -greater than 320 pixels wide. - -On network connections that dropped packets, the reliable message stream -could get stopped up, resulting in frag counts and talk messages no longer -being delivered, although game movement continued. - -The com port settings from the menu were getting saved & restored but -not used. - -Direct serial connections did not work with slist. - -Quake now checks the vesa information for hardware incabable of page-flipping. - -Menu sound sometimes didn't play. - -Q95 (qlaunch.exe) frequently failed to execute on the first attempt. - -Q95 (quakeudp.dll) was running out of buffers when running a server. - -Teams were not being set according to pants colors. - - -Joystick notes --------------- -Your joystick must be plugged in when Quake is launched. - -If you have a joystick plugged in, but don't want to use it in Quake -(it slows the game down a few percent), or you have weird hardware that -doesn't like being tested as a joystick add "-nojoy" to your Quake -command line. - -You can turn off joystick reading during the game by typing "joystick 0" at -the Quake command console. - -You MUST configure your buttons from the configure keys menu before they will -work. There is no default configuration. - -If your joystick or interface card improperly sets the third or fourth -joystick buttons, type "joybuttons 2" at the quake console or in your -.CFG file. - -The "mlook" button command now lets the joystick as well as the mouse control -pitch angles. - -The "sidestep" buttom command works on joysticks as with mice and keyboard -movement. - -The "invert mouse up/down" menu option also inverts the joystick pitch -direction. +Welcome to Quake! + +This file details how to get Quake running on your system and what to do +if you have problems. We would like to thank Gandalf Technologies, Inc and +MPath Interactive for the use of their technology. We would also like to +thank Trent Reznor and Nine Inch Nails for their tremendous contributions +to Quake's entire audio portion. + +The NIN logo is a Registered Trademark licensed to Nothing Interactive, Inc. +All Rights Reserved. + +Quake System Requirements +------------------------- +IBM PC and Compatibles +Pentium processor or better +VGA Compatible Display or better +8MB RAM minimum, 16MB recommended (16 MB required for running under Win95) +CD-ROM drive Required +MS-DOS 5.0 or better or Windows 95 (does NOT run under Windows NT) +Hard Drive (30MB for Shareware, 80 MB for Registered) + +*** IMPORTANT!: Quake requires a floating point processor. +Systems that do not have an FPU installed will not run Quake -- at all. + +*** IMPORTANT Video Adapter Note! *** +On some ATI Mach32 cards, Quake can come up with a garbled video display. +This is due to a problem with the card in which 320x200 mode isn't +initialized correctly. Workarounds include: + +1) If running from Windows, start Quake from an icon, or from a windowed +(not fullscreen) MS-DOS prompt. If Quake is already running and has +the garbled screen, press Alt-Enter twice to switch to the desktop and +back to fullscreen, and the screen will display properly. + +2) If running from DOS, either put the line + +vid_mode 1 + +in id1\autoexec.cfg, or, typing blind, press tilde ('~') to bring down +the console, type + +vid_mode 1 + +and the screen will display properly. + +======================================================================== +Here are the text files included with the shareware release of Quake and +what they are: + +README.TXT This file +TECHINFO.TXT Technical information on Quake's subsystems and + their advanced use. +MANUAL.TXT Text version of the printed game manual +LICINFO.TXT Info on the various license files included with Quake +SLICNSE.TXT Shareware Quake end-user license +ORDER.TXT How to order Quake +HELP.TXT How to get help with Quake + +Here are the text files included with the registered version of Quake and +what they are: + +README.TXT This file +TECHINFO.TXT Technical information on Quake's subsystems and + their advanced use. +MANUAL.TXT Text version of the printed game manual +LICINFO.TXT Info on the various license files included with Quake +RLICNSE.TXT Registered Quake end-user license +COMEXP.TXT Commercial exploitation agreement +ORDER.TXT How to order Quake +HELP.TXT How to get help with Quake + + +Running Quake +------------- + +DOS: To launch Quake from the DOS Prompt, go to the Quake directory and +simply type "QUAKE" . (no quotes) + +Windows 95: To launch Quake in single player mode, double click on the file +QUAKE.EXE From Windows Explorer. To run Quake in Multi-Player mode using +the TCP/IP protocol, first check your network settings to ensure the +protocol is installed, then double click on the Q95.BAT file to launch the +game. In this version (v0.91) there is a minor bug that will cause the +Q95.BAT file to exit the first time you run it, without running Quake. +Merely double-click on that file again and it will work. + +Audio Setup +----------- + +When using a Sound Card with Quake, there are a few setup steps which must +be taken. First, the "BLASTER" environment variable setting must be in your +autoexec.bat (or you can type it in manually from the MS-DOS command prompt). +Running the Sound Blaster utility diagnose.exe will automatically configure +your sound card and put this statement in your autoexec.bat file for you. +A typical blaster setting looks like this (although yours may vary): + +SET BLASTER=A220 I5 D1 H5 P330 T6 + +If you want to play the audio track from the CD-ROM while playing Quake, +you must ensure that the audio cable from the CD-ROM is connected to the +sound card. + +If you think your sound card is setup properly and it STILL doesn't work, +check to make sure that your BLASTER environment variable contains the +high DMA setting (H5 in the above example). + +If you don't get sound while trying to play the audio track, check to see +if a small cable goes from the back of your CD-ROM player directly to your +sound card. If the CD-ROM audio cable is connected to your sound board (or +the motherboard in some cases) and you STILL don't hear CD Audio coming from +your speakers, make sure the MIXER program has the CD volume turned up. +You will also need to run the CD-ROM driver MSCDEX.EXE. Here is an example +of the files you should see (yours probably will vary) listed in your +CONFIG.SYS and AUTOEXEC.BAT (explanation is in parentheses): + +CONFIG.SYS: + +DEVICE=C:\PROSCSI\CDROM.SYS /D:PROCD01 (CD-ROM driver) + +AUTOEXEC.BAT: + +SET BLASTER=A220 I5 D1 H5 P330 T6 (sound environment variable setting) +C:\WINDOWS\COMMAND\MSCDEX.EXE /D:PROCD01 /L:D (CD-ROM driver) + +=================================================== +UltraSound MAX and UltraSound PnP Support for Quake +=================================================== + +Before running Quake, make sure that your sound card works and your +environment variables are set correctly. + +Other UltraSound Cards (ACE & Classic) +-------------------------------------- +These drivers are not for the UltraSound ACE or UltraSound Classic +sound cards. We have heard mixed reports that MegaEm or SBOS +have a chance of working with the UltraSound Classic but there is a +short sound F/X delay. + +UltraSound PnP and PnP Pro +-------------------------- +You must make sure that you do NOT have IWSBOS or MegaEm loaded. + +Setup +----- +Quake will automatically detect that the UltraSound Max or PnP +are installed. It does this by looking at the SET INTERWAVE (PnP) +and SET ULTRA16 (Max) environment variables. + +Quake will use the settings found on the SET ULTRASND/ULTRA16 (Max) +and in the IW.INI (PnP) file to determine what port settings to use. + +Troubleshooting Windows 95 (DOS Box) +------------------------------------ +We recommend that you restart your computer in MS-DOS Mode. DOS Box +may or may not work, so use at your own risk. + +CD Audio Input +-------------- +If you have not already enabled CD audio output by default you will +need to enable it. For the UltraSound MAX you can run "ULTRINIT -EC". +For the UltraSound PnP you will need to enable the CD audio output +in Win'95 and then restart your computer into MS-DOS. + +=================================================== +Mouse Setup +----------- + +If you are going to use a mouse when playing Quake, you will need to load +your mouse driver. This should go in the AUTOEXEC.BAT file as well. Here +is an example: + +C:\LOGITECH\MOUSE\MOUSE.EXE (mouse driver) + + +Booting Clean +------------- + +If you are going to be running Quake with only 8 megabytes of RAM, it is best +to boot clean . You eliminate unwanted utilities or applications from taking +up valuable memory, without having to alter your regular AUTOEXEC.BAT and +CONFIG.SYS. Booting clean can be done in one of two ways. If you have +MS-DOS version 6.xx, booting clean is as simple a pressing the shift key +when you see the words "Starting MS-DOS". If you have MS-DOS ver 5.xx you +will need to make a system disk. + +To make a boot disk, type the following from the MS-DOS command prompt: + +FORMAT A: /S + +1. Make sure that this is a disk you wish to erase. +2. This disk absolutely HAS to be formatted in the A: drive. + +To use the system disk, place the disk in the A: drive and reset the +computer. + +NOTE: If your sound card requires a driver to be loaded, or you will be +using a mouse, or you will be using Quake's CD audio feature, the system +disk will need to have a CONFIG.SYS and AUTOEXEC.BAT that load the +appropriate drivers. + +Creating a Quake Shortcut + +As an alternative to making a Boot Disk, Windows 95 users can create a +Quake Shortcut. By double clicking onthis shortcut, Windows 95 will reboot +in MS-DOS mode and install only the desired drivers, giving you the same +results as using a Boot Disk. To create a Quake Shortcut, do the following: + +1. Using Explorer, right click and drag the file QUAKE.EXE, from the Quake + directory, to your desktop. Windows 95 will make an MS-DOS Icon titled + "Shortcut to quake". +2. Right click on the new icon, and from the menu that pops up, choose + "Properties". Then choose the "Program" tab at the top. +3. Now click on the "Advanced..." button near the bottom. The "Advanced + Program Settings" window should appear. +4. Select the "MS-DOS mode" check box and the "Specify a new MS-DOS + configuration" option button. +5. Now simply fill in the "CONFIG.SYS for MS-DOS mode:" and "AUTOEXEC.BAT + for MS-DOS mode:" boxes with the same sound, CD-ROM and mouse settings as + mentioned above in the Boot Disks section. +6. Click on "OK" when you are finished. If you wish, you can change your + Quake Shortcut Icon to something a little more exciting by clicking on + "Change Icon...". +7. To finish, click on "OK" again. + 8. You can rename your Quake Shortcut by right clicking on the shortcut + icon, choosing "Rename" and typing in the new name. + + +====================================================== +== Known Problems == +====================================================== + +Problem: Zombies sometime get stuck on the ground and connot get back up. +(You can still hear them, but you cannot kill them. This bug makes it +impossible to get 100% kills on whatever level it occurs on.) +Solution: There is no workaround for this bug. + +Problem: It is sometimes possible for the player to get stuck in a room or +in a wall. +Solution: If you get stuck, use the 'kill' console command. It is a good +idea to save your game often. + +Problem: View centering problems. Sometimes during a game, the view will not +center properly. The end result is the player view looking up torwards the +ceiling while walking. +Solution: Exit to the next level or use the 'kill' console command.. + + +====================================================== +== Troubleshooting == +====================================================== + +If Quake fails to start up, or has problems not addressed elsewhere in the +documentation, try the -safe command line switch, which disables a number +of parts of Quake that can be problems if there are hardware or configuration +problems. The -safe command line switch is equivalent to -stdvid, -nosound, +-nonet, and -nocdaudio together. Those four switches do the following: + +-stdvid: disables VESA video modes. + +-nosound: disables sound card support. + +-nonet: disables network card support. + +-nocdaudio: disables CD audio support. + +If -safe makes the problem go away, try using each of the switches +individually to isolate the area in which you're experiencing the problem, +then either correct the configuration or hardware problem or play Quake with +that functionality disabled. + +If you still have problems, try booting clean in conjunction with +the -safe command line parameter. For information on booting clean, refer +to the "Booting Clean" section above. + +If you experience page faults while running Quarterdeck's QDPMI DPMI server, +this is caused by a bug in QDPMI. Workarounds: Remove QDPMI from CONFIG.SYS, +issue the command QDPMI OFF before running QUAKE, or get the update patch +for QDPMI from Quarterdeck. You may be running QDPMI without knowing it if +you have QEMM installed, because it can be installed as part of the QEMM +installation. + + +Technical Support +----------------- + +If you are having trouble installing or running Quake you can receive +technical support by sending e-mailing to support@idsoftware.com. You can +also refer to our web page, www.idsoftware.com, or call 1-800-idgames. + +When sending support e-mail, cut and paste the following into your e-mail +message and fill in the blanks: + +Date: +Name: +Phone number: +E-mail address: (please include this, we redirect tons of mail) +Game Title: +Version #: +Operating system (i.e., DOS 6.0 or Windows 95): +Computer type: +BIOS date: +BIOS version: +Processor type: +Processor speed: +Do you program at school/work? +Do you provide tech. support at school/work? +Please state the problem you encountered: +Please state how to reproduce the problem: + +If program crashed with nasty undecipherable techno-garbage, please +look for the eight-digit hex number which comes after "eip=" +and write it down here: + +** NOTE: If you are sending a bug report, PLEASE refer to the TECHINFO.TXT +file for the correct form and procedures. + + +====================================================== +== Version History == +====================================================== +v1.01 -- Bugs fixed +------------------------------------------------------ +* Fixed modem code +* Fixed fraglimit & timelimit +* Added NOEXIT cvar (so no one can exit a level) +------------------------------------------------------ +v1.00 -- Bugs fixed +------------------------------------------------------ +* Gravis Ultrasound audio support (still has bugs) +* More deathmatch start spots on E1M6 and END +* Print server version and PROG CRC on connect +* -dedicated starts start.map if nothing else specified +* fixed lookspring function during net game +* fixed rare crash during long running dedicated server +------------------------------------------------------ +v0.94 -- Bugs fixed / Features added -- LIMITED BETA VERSION +------------------------------------------------------ +* Totally rewritten menus +* New lighting model with overbrighting +* Parsed lowercase BLASTER parms +* Better Sound Blaster shutdown code +* Rewrote BLASTER initialization +* Fixed DMA channel 0 bugs +* Added SBPro 8 stereo setup +* Fix delayed sound on 8 bit Sound Blasters +* Fixed speed key affecting angle-turning from keyboard +* Fixed "no such Alias frame" bugs +* Fixed Zombie not getting up bug +* Checked for very high joystick values, signalling a failed read +* Unstuck jumping Fiends and Spawn +* Fixed large BModels blinking out in complex areas +* Fixed s_localsound with no sound started +* Saved spawn parms in savegame +* Fixed screenshot save location +* Bind with no arguments no longer clears value +* Allow console in intermission / finale +* Fixed false gib messages +* Full-screen TAB scoreboard in DeathMatch +* Fixed "+playdemo " from command line +* Trapped overflow in sizebuf messages +* Moveup / movedown in water! +* Fixed-up Talk command +* Added unsupported crosshair option ("crosshair 1" from console) +* Colored chat messages with notify sound +* Fixed "connect during intermission" bug +* Changelevel while demos running no longer crashes +* Fixed changelevel with no map left up loading screen +* Fixed long names entered from the console causing crash +* Stopped demos changing while in the menus + +* Fixed modem initialization from menu +* Fixed serial reliable stream getting stalled +* Serial/modem code fixes + 16550a lost transmit buffer empty interrupts + fixed sometimes processing interrupts from com1 when using com2 + added com3/com4 support from menus + fixed first character of modem init not getting sent + saved serial/modem settings in config.cfg +* Fixed name and colors not always sent to server at startup +* Fixed "stopdemo" crashing the system when there wasn't a demo playing +* Added server's TCP/IP and IPX addresses (if available) to status command + +* In 0.92, an additional check for a usable VESA video mode was added; +the numpages field was verified to be greater than 0, and no mode was +supported that had numpages set to 0 (which indicates that there's not +enough video memory for that mode). ATI's VESA driver, m64vbe, +reports 0 for numpages, so VESA video modes that were available in 0.91 +were no longer available in 0.92. This extra numpages check has +been removed. + +----------------------------------------------------------------------- +v0.93 -- Never officially released; internal testing only. +----------------------------------------------------------------------- +v0.92 -- Bugs fixed +----------------------------------------------------------------------- +Typing long strings in the hostname or modem init field in the menus caused +crashes. + +Under Win95 IPX was detected but not functional, resulting in the game +exiting to DOS. + +If -nosound, got "S_LocalSound: can't cache" on every keypress in the menu. + +When vid_nopageflip was set to 1 in VESA modes, going underwater resulted in +only the upper left corner of the drawing area being updated. + +The single player scoreboard (tab) printed text incorrectly in all modes +greater than 320 pixels wide. + +On network connections that dropped packets, the reliable message stream +could get stopped up, resulting in frag counts and talk messages no longer +being delivered, although game movement continued. + +The com port settings from the menu were getting saved & restored but +not used. + +Direct serial connections did not work with slist. + +Quake now checks the vesa information for hardware incabable of page-flipping. + +Menu sound sometimes didn't play. + +Q95 (qlaunch.exe) frequently failed to execute on the first attempt. + +Q95 (quakeudp.dll) was running out of buffers when running a server. + +Teams were not being set according to pants colors. + + +Joystick notes +-------------- +Your joystick must be plugged in when Quake is launched. + +If you have a joystick plugged in, but don't want to use it in Quake +(it slows the game down a few percent), or you have weird hardware that +doesn't like being tested as a joystick add "-nojoy" to your Quake +command line. + +You can turn off joystick reading during the game by typing "joystick 0" at +the Quake command console. + +You MUST configure your buttons from the configure keys menu before they will +work. There is no default configuration. + +If your joystick or interface card improperly sets the third or fourth +joystick buttons, type "joybuttons 2" at the quake console or in your +.CFG file. + +The "mlook" button command now lets the joystick as well as the mouse control +pitch angles. + +The "sidestep" buttom command works on joysticks as with mice and keyboard +movement. + +The "invert mouse up/down" menu option also inverts the joystick pitch +direction. diff --git a/WinQuake/data/RLICNSE.TXT b/WinQuake/data/RLICNSE.TXT index a3fdc35..a8ab828 100644 --- a/WinQuake/data/RLICNSE.TXT +++ b/WinQuake/data/RLICNSE.TXT @@ -1,204 +1,204 @@ -REGISTERED VERSION: QUAKE -LIMITED USE SOFTWARE LICENSE AGREEMENT - - This Limited Use Software License Agreement (the -"Agreement") is a legal agreement between you, the end-user, and Id -Software, Inc. ("ID"). By continuing the installation of this game -program, by loading or running the game, or by placing or copying -the game program onto your computer hard drive, you are agreeing to -be bound by the terms of this Agreement. If you do not agree to -the terms of this Agreement, promptly return the game program and -the accompanying items (including all written materials), along -with your receipt to the place from where you obtained them for a -full refund. - -ID SOFTWARE LICENSE - - 1. Grant of License. ID grants to you the limited -right to use one (1) copy of the enclosed or foregoing game program -(the "Software") on a single computer. You have no ownership or -proprietary rights in or to the Software or the written materials -accompanying the Software. For purposes of this section, "use" -means loading the Software into RAM, as well as installation on a -hard disk or other storage device. You may create a map editor, -modify maps and make your own maps (collectively referenced as the -"Permitted Derivative Works") for the Software. Permitted -Derivative Works may not be sold, whether by you or by any other -person or entity, but you may exchange the Permitted Derivative -Works at no charge amongst other end-users. The Software, together -with any archive copy thereof, shall be either returned to ID or -destroyed when no longer used in accordance with this Agreement, or -when the right to use the Software is terminated. You agree that -the Software will not be shipped, transferred or exported into any -country in violation of the U.S. Export Administration Act (or any -other law governing such matters) and that you will not utilize, in -any other manner, the Software in violation of any applicable law. - - 2. Commercial Use is Prohibited. Except as provided in -paragraph 5. hereinbelow in regard to the Software, under no -circumstances shall you, the end-user, be permitted, allowed or -authorized to commercially exploit the Software, any data -comprising the Software. Neither you nor anyone at your direction -shall do any of the following acts (any such acts shall be deemed -void and a breach of this Agreement) with regard to the Software, -or any portion thereof, such as a screen display or a screenshot: - - a. Rent the Software; - - b. Sell the Software; - - c. Lease or lend the Software; - - d. Offer the Software on a pay-per-play basis; - - e. Distribute, by electronic means or otherwise, the - Software for money or any other consideration; or - - f. In any other manner and through any medium - whatsoever commercially exploit the Software or use - the Software for any commercial purpose. - - 3. Additional Prohibited Uses. Neither you nor anyone -at your direction shall take the following action in regard to the -Software, or any portion thereof, such as a screen display or a -screenshot: - - a. Modify, disassemble, reverse engineer or decompile - the Software; - - b. Translate the Software; - - c. Reproduce the Software; - - d. Publicly display the Software; - - e. Prepare derivative works based upon the Software - (except Permitted Derivative Works); or - - f. Distribute, by electronic means or otherwise, the - Software. - - 4. Use of Other Material is Prohibited. Use, in any manner, of - the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, - art work, images, screen displays or screenshots, sound effects, music, - and other such material contained within, generated by or relating to - the Software is prohibited. - - 5. To Receive Permission to Commercially Exploit. If -you desire to commercially exploit the Software, you may execute -the Commercial Exploitation License Agreement for QUAKE (the -"License") contained within the QUAKE install package and forward -the original License to Id Software at the address noted therein. -Please note that ID may refuse your request and not sign the -License in ID's sole discretion. - - 6. Restrictions Apply to Third Parties. The -prohibitions and restrictions described herein apply to anyone in -possession of the Software and/or Permitted Derivative Works. - - 7. Copyright. The Software and all copyrights related -thereto (including all characters and other images generated by the -Software or depicted in the Software) is owned by ID and is protected -by United States copyright laws and international treaty provisions. -You must treat the Software like any other copyrighted material, -except that you may either (a) make one copy of the Software solely -for back-up or archival purposes, or (b) transfer the Software to a -single hard disk provided you keep the original solely for back-up or -archival purposes. You may not otherwise reproduce, copy or disclose -to others, in whole or in any part, the Software. You may not copy -the written materials accompanying the Software. The same -restrictions and prohibitions regarding your use of the Software as -provided in this Agreement apply to your use of the written materials -accompanying the Software. The written materials are owned by ID and -are protected by United States copyright laws and international -treaties. You agree to use your best efforts to see that any user of -the Software licensed hereunder complies with this Agreement. - - 8. Limited Warranty. ID warrants that if properly -installed and operated on a computer for which it is designed, the -Software will perform substantially in accordance with the -accompanying written materials for a period of ninety (90) days -from the date of purchase of the Software. ID's entire liability -and your exclusive remedy shall be, at ID's option, either (a) -return of the price paid or (b) repair or replacement of the -Software that does not meet ID's Limited Warranty. To make a -warranty claim, return the Software to the point of purchase, -accompanied by proof of purchase, your name, your address, and a -statement of defect, or return the Software with the above -information to ID. This Limited Warranty is void if failure of the -Software has resulted in whole or in part from accident, abuse, -misapplication or violation of this Agreement. Any replacement -Software will be warranted for the remainder of the original -warranty period or thirty (30) days from your receipt of the -replacement software, whichever is longer. This warranty allocates -risks of product failure between Licensee and ID. ID's product -pricing reflects this allocation of risk and the limitations of -liability contained in this warranty. - - 9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER -WARRANTIES, BOTH EXPRESS IMPLIED, INCLUDING BUT NOT LIMITED TO, -IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR -PURPOSE WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN -MATERIALS. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. -YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO -JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE -SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S -SPECIFIC REQUIREMENTS. THE WARRANTY SET FORTH ABOVE IS IN LIEU OF -ALL OTHER EXPRESS WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, -EMPLOYEES, DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO -MAKE MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON -BEHALF OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR -PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE -WARRANTIES BY ID AND SHOULD NOT BE RELIED UPON. - - 10. Exclusive Remedies. You agree that your exclusive -remedy against ID, its affiliates, contractors, suppliers, and -agents for loss or damage caused by any defect or failure in the -Software regardless of the form of action, whether in contract, -tort, including negligence, strict liability or otherwise, shall be -the return of the purchase price paid or replacement of the -Software. This Agreement shall be construed in accordance with and -governed by the laws of the State of Texas. Copyright and other -proprietary matters will be governed by United States laws and -international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR -LOSS OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, -CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM -BREACH OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL -THEORY EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY -OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some -jurisdictions do not allow the exclusion or limitation of -incidental or consequential damages, so the above limitation or -exclusion may not apply to you. - - 11. General Provisions. Neither this Agreement nor any -part or portion hereof shall be assigned, sublicensed or otherwise -transferred by you. Should any provision of this Agreement be held -to be void, invalid, unenforceable or illegal by a court, the -validity and enforceability of the other provisions shall not be -affected thereby. If any provision is determined to be -unenforceable, you agree to a modification of such provision to -provide for enforcement of the provision's intent, to the extent -permitted by applicable law. Failure of a party to enforce any -provision of this Agreement shall not constitute or be construed as -a waiver of such provision or of the right to enforce such -provision. If you fail to comply with any terms of this Agreement, -YOUR LICENSE IS AUTOMATICALLY TERMINATED. - - YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, THAT YOU -UNDERSTAND THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE -INSTALLATION OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR -BY PLACING OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU -AGREE TO BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU -FURTHER AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID -AND YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE -RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES ALL -PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY OTHER -COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT MATTER OF -THIS AGREEMENT. - -June 21, 1996 - -REGISTERED VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT Page 4 -(DWC:dw:3406.0024:DWC\doc:1164) - - +REGISTERED VERSION: QUAKE +LIMITED USE SOFTWARE LICENSE AGREEMENT + + This Limited Use Software License Agreement (the +"Agreement") is a legal agreement between you, the end-user, and Id +Software, Inc. ("ID"). By continuing the installation of this game +program, by loading or running the game, or by placing or copying +the game program onto your computer hard drive, you are agreeing to +be bound by the terms of this Agreement. If you do not agree to +the terms of this Agreement, promptly return the game program and +the accompanying items (including all written materials), along +with your receipt to the place from where you obtained them for a +full refund. + +ID SOFTWARE LICENSE + + 1. Grant of License. ID grants to you the limited +right to use one (1) copy of the enclosed or foregoing game program +(the "Software") on a single computer. You have no ownership or +proprietary rights in or to the Software or the written materials +accompanying the Software. For purposes of this section, "use" +means loading the Software into RAM, as well as installation on a +hard disk or other storage device. You may create a map editor, +modify maps and make your own maps (collectively referenced as the +"Permitted Derivative Works") for the Software. Permitted +Derivative Works may not be sold, whether by you or by any other +person or entity, but you may exchange the Permitted Derivative +Works at no charge amongst other end-users. The Software, together +with any archive copy thereof, shall be either returned to ID or +destroyed when no longer used in accordance with this Agreement, or +when the right to use the Software is terminated. You agree that +the Software will not be shipped, transferred or exported into any +country in violation of the U.S. Export Administration Act (or any +other law governing such matters) and that you will not utilize, in +any other manner, the Software in violation of any applicable law. + + 2. Commercial Use is Prohibited. Except as provided in +paragraph 5. hereinbelow in regard to the Software, under no +circumstances shall you, the end-user, be permitted, allowed or +authorized to commercially exploit the Software, any data +comprising the Software. Neither you nor anyone at your direction +shall do any of the following acts (any such acts shall be deemed +void and a breach of this Agreement) with regard to the Software, +or any portion thereof, such as a screen display or a screenshot: + + a. Rent the Software; + + b. Sell the Software; + + c. Lease or lend the Software; + + d. Offer the Software on a pay-per-play basis; + + e. Distribute, by electronic means or otherwise, the + Software for money or any other consideration; or + + f. In any other manner and through any medium + whatsoever commercially exploit the Software or use + the Software for any commercial purpose. + + 3. Additional Prohibited Uses. Neither you nor anyone +at your direction shall take the following action in regard to the +Software, or any portion thereof, such as a screen display or a +screenshot: + + a. Modify, disassemble, reverse engineer or decompile + the Software; + + b. Translate the Software; + + c. Reproduce the Software; + + d. Publicly display the Software; + + e. Prepare derivative works based upon the Software + (except Permitted Derivative Works); or + + f. Distribute, by electronic means or otherwise, the + Software. + + 4. Use of Other Material is Prohibited. Use, in any manner, of + the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, + art work, images, screen displays or screenshots, sound effects, music, + and other such material contained within, generated by or relating to + the Software is prohibited. + + 5. To Receive Permission to Commercially Exploit. If +you desire to commercially exploit the Software, you may execute +the Commercial Exploitation License Agreement for QUAKE (the +"License") contained within the QUAKE install package and forward +the original License to Id Software at the address noted therein. +Please note that ID may refuse your request and not sign the +License in ID's sole discretion. + + 6. Restrictions Apply to Third Parties. The +prohibitions and restrictions described herein apply to anyone in +possession of the Software and/or Permitted Derivative Works. + + 7. Copyright. The Software and all copyrights related +thereto (including all characters and other images generated by the +Software or depicted in the Software) is owned by ID and is protected +by United States copyright laws and international treaty provisions. +You must treat the Software like any other copyrighted material, +except that you may either (a) make one copy of the Software solely +for back-up or archival purposes, or (b) transfer the Software to a +single hard disk provided you keep the original solely for back-up or +archival purposes. You may not otherwise reproduce, copy or disclose +to others, in whole or in any part, the Software. You may not copy +the written materials accompanying the Software. The same +restrictions and prohibitions regarding your use of the Software as +provided in this Agreement apply to your use of the written materials +accompanying the Software. The written materials are owned by ID and +are protected by United States copyright laws and international +treaties. You agree to use your best efforts to see that any user of +the Software licensed hereunder complies with this Agreement. + + 8. Limited Warranty. ID warrants that if properly +installed and operated on a computer for which it is designed, the +Software will perform substantially in accordance with the +accompanying written materials for a period of ninety (90) days +from the date of purchase of the Software. ID's entire liability +and your exclusive remedy shall be, at ID's option, either (a) +return of the price paid or (b) repair or replacement of the +Software that does not meet ID's Limited Warranty. To make a +warranty claim, return the Software to the point of purchase, +accompanied by proof of purchase, your name, your address, and a +statement of defect, or return the Software with the above +information to ID. This Limited Warranty is void if failure of the +Software has resulted in whole or in part from accident, abuse, +misapplication or violation of this Agreement. Any replacement +Software will be warranted for the remainder of the original +warranty period or thirty (30) days from your receipt of the +replacement software, whichever is longer. This warranty allocates +risks of product failure between Licensee and ID. ID's product +pricing reflects this allocation of risk and the limitations of +liability contained in this warranty. + + 9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER +WARRANTIES, BOTH EXPRESS IMPLIED, INCLUDING BUT NOT LIMITED TO, +IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN +MATERIALS. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. +YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO +JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE +SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S +SPECIFIC REQUIREMENTS. THE WARRANTY SET FORTH ABOVE IS IN LIEU OF +ALL OTHER EXPRESS WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, +EMPLOYEES, DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO +MAKE MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON +BEHALF OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR +PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE +WARRANTIES BY ID AND SHOULD NOT BE RELIED UPON. + + 10. Exclusive Remedies. You agree that your exclusive +remedy against ID, its affiliates, contractors, suppliers, and +agents for loss or damage caused by any defect or failure in the +Software regardless of the form of action, whether in contract, +tort, including negligence, strict liability or otherwise, shall be +the return of the purchase price paid or replacement of the +Software. This Agreement shall be construed in accordance with and +governed by the laws of the State of Texas. Copyright and other +proprietary matters will be governed by United States laws and +international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR +LOSS OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, +CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM +BREACH OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL +THEORY EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some +jurisdictions do not allow the exclusion or limitation of +incidental or consequential damages, so the above limitation or +exclusion may not apply to you. + + 11. General Provisions. Neither this Agreement nor any +part or portion hereof shall be assigned, sublicensed or otherwise +transferred by you. Should any provision of this Agreement be held +to be void, invalid, unenforceable or illegal by a court, the +validity and enforceability of the other provisions shall not be +affected thereby. If any provision is determined to be +unenforceable, you agree to a modification of such provision to +provide for enforcement of the provision's intent, to the extent +permitted by applicable law. Failure of a party to enforce any +provision of this Agreement shall not constitute or be construed as +a waiver of such provision or of the right to enforce such +provision. If you fail to comply with any terms of this Agreement, +YOUR LICENSE IS AUTOMATICALLY TERMINATED. + + YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, THAT YOU +UNDERSTAND THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE +INSTALLATION OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR +BY PLACING OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU +AGREE TO BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU +FURTHER AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID +AND YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE +RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES ALL +PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY OTHER +COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT MATTER OF +THIS AGREEMENT. + +June 21, 1996 + +REGISTERED VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT Page 4 +(DWC:dw:3406.0024:DWC\doc:1164) + + diff --git a/WinQuake/data/SLICNSE.TXT b/WinQuake/data/SLICNSE.TXT index 057302b..59c6733 100644 --- a/WinQuake/data/SLICNSE.TXT +++ b/WinQuake/data/SLICNSE.TXT @@ -1,175 +1,175 @@ -SHAREWARE VERSION: QUAKE -LIMITED USE SOFTWARE LICENSE AGREEMENT - - This Limited Use Software License Agreement (the "Agreement") is a - legal agreement between you, the end-user, and id Software, Inc. - ("ID"). By continuing the installation of this game program, by - loading or running the game, or by placing or copying the game - program onto your computer hard drive, you are agreeing to be bound - by the terms of this Agreement. - -ID SOFTWARE LICENSE - - 1. Grant of License. ID grants to you the limited right to use - one (1) copy of the enclosed or foregoing Id Software game program - (the "Software"), which is the shareware version or episode one of - the game program. For purposes of this section, "use" means loading - the Software into RAM, as well as installation on a hard disk or - other storage device. You agree that the Software will not be - shipped, transferred or exported into any country in violation of - the U.S. Export Administration Act (or any other law governing such - matters) and that you will not utilize, in any other manner, the - Software in violation of any applicable law. - - 2. Commercial Use is Prohibited. Under no circumstances shall - you, the end-user, be permitted, allowed or authorized to - commercially exploit the Software, or any portion thereof, such - as a screen display or a screenshot. Neither you nor anyone at your - direction shall do any of the following acts: - - a. Rent the Software; - - b. Sell the Software; - - c. Lease or lend the Software; - - d. Offer the Software on a pay-per-play basis; - - e. Distribute the Software for money or any other - consideration; or - - f. In any other manner and through any medium - whatsoever commercially exploit the Software or use - the Software for any commercial purpose. - - 3. Additional Prohibited Uses. Neither you, nor anyone at your - direction, shall take the following action in regard to the - Software, or any portion thereof, such as a screen display or - a screenshot: - - a. Modify, disassemble, reverse engineer or decompile - the Software; - - b. Translate the Software; - - c. Reproduce the Software; - - d. Publicly display the Software; or - - e. Prepare derivative works based upon the Software. - - 4. Use of Other Material is Prohibited. Use, in any manner, of - the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, - art work, images, screen displays or screenshots, sound effects, music, - and other such material contained within, generated by or relating to - the Software is prohibited. - - 5. Restrictions Apply to Third Parties. The prohibitions and - restrictions described herein apply to anyone in possession of - the Software. - - 6. Permitted Distribution. So long as this Agreement - accompanies the Software at all times, ID grants to Providers the - limited right to distribute, free of charge, except normal access - fees, and by electronic means only, the Software; provided, however, - the Software must be so electronically distributed only in a - compressed format. The term "Providers," as used in the foregoing - sentence, shall mean persons whose business it is to provide - services on the Internet, on commercial online networks, or on the - BBS. Anyone who receives the Software from a Provider shall be - limited to all the terms and conditions of this Agreement. Further, - ID grants to you, the end-user, the limited right to distribute, - free of charge only, the Software as a whole. - - 7. Copyright. The Software is owned by ID and is protected by - United States copyright laws and international treaty provisions. - You must treat the Software like any other copyrighted material, - except that you may make copies of the Software to give to other - persons. You may not charge or receive any consideration from any - other person for the receipt or use of the Software. You agree to - use your best efforts to see that any user of the Software licensed - hereunder complies with this Agreement. - - 8. Limited Warranty. ID warrants that if properly installed and - operated on a computer for which it is designed, the Software will - perform substantially in accordance with its designed purpose for a - period of ninety (90) days from the date the Software is first - obtained by an end-user. ID's entire liability and your exclusive - remedy shall be, at ID's option, either (a) return of the retail - price paid, if any, or (b) repair or replacement of the Software - that does not meet ID's Limited Warranty. To make a warranty claim, - return the Software to the point of purchase, accompanied by proof - of purchase, your name, your address, and a statement of defect, or - return the Software with the above information to ID. This Limited - Warranty is void if failure of the Software has resulted in whole - or in part from accident, abuse, misapplication or violation of this - Agreement. Any replacement Software will be warranted for the - remainder of the original warranty period or thirty (30) days, - whichever is longer. This warranty allocates risks of product - failure between Licensee and ID. ID's product pricing reflects this - allocation of risk and the limitations of liability contained in - this warranty. - - 9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER WARRANTIES, - EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED - WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A pARTICULAR PURPOSE - WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN MATERIALS, - IF ANY. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. YOU - MAY HAVE OTHERS WHICH VARY FROM JURISDICTION TO JURISDICTION. ID - DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE - UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S SPECIFIC REQUIREMENTS. - THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS - WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES, - DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE - MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF - OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR - PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE WARRANTIES - BY ID AND SHOULD NOT BE RELIED UPON. - - 10. Exclusive Remedies. You agree that your exclusive remedy - against ID, its affiliates, contractors, suppliers, and agents for - loss or damage caused by any defect or failure in the Software - regardless of the form of action, whether in contract,tort, - including negligence, strict liability or otherwise, shall be the - return of the retail purchase price paid, if any, or replacement of - the Software. This Agreement shall be construed in accordance with - and governed by the laws of the State of Texas. Copyright and other - proprietary matters will be governed by United States laws and - international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR LOSS - OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, - CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM BREACH - OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL THEORY - EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do - not allow the exclusion or limitation of incidental or consequential - damages, so the above limitation or exclusion may not apply to you. - - 11. General Provisions. Neither this Agreement nor any part or - portion hereof shall be assigned or sublicensed, except as described - herein. Should any provision of this Agreement be held to be void, - invalid, unenforceable or illegal by a court, the validity and - enforceability of the other provisions shall not be affected thereby. - If any provision is determined to be unenforceable, you agree to a - modification of such provision to provide for enforcement of the - provision's intent, to the extent permitted by applicable law. Failure - of a party to enforce any provision of this Agreement shall not - constitute or be construed as a waiver of such provision or of the - right to enforce such provision. If you fail to comply with any terms - of this Agreement, YOUR LICENSE IS AUTOMATICALLY TERMINATED. - - YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, YOU UNDERSTAND - THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE INSTALLATION - OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING - OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU AGREE TO - BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU FURTHER - AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID AND - YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE - RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES - ALL PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY - OTHER COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT - MATTER OF THIS AGREEMENT. - -June 21, 1996 - -SHAREWARE VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT -(DWC:dw:3406.0024:DWC\doc:1163) +SHAREWARE VERSION: QUAKE +LIMITED USE SOFTWARE LICENSE AGREEMENT + + This Limited Use Software License Agreement (the "Agreement") is a + legal agreement between you, the end-user, and id Software, Inc. + ("ID"). By continuing the installation of this game program, by + loading or running the game, or by placing or copying the game + program onto your computer hard drive, you are agreeing to be bound + by the terms of this Agreement. + +ID SOFTWARE LICENSE + + 1. Grant of License. ID grants to you the limited right to use + one (1) copy of the enclosed or foregoing Id Software game program + (the "Software"), which is the shareware version or episode one of + the game program. For purposes of this section, "use" means loading + the Software into RAM, as well as installation on a hard disk or + other storage device. You agree that the Software will not be + shipped, transferred or exported into any country in violation of + the U.S. Export Administration Act (or any other law governing such + matters) and that you will not utilize, in any other manner, the + Software in violation of any applicable law. + + 2. Commercial Use is Prohibited. Under no circumstances shall + you, the end-user, be permitted, allowed or authorized to + commercially exploit the Software, or any portion thereof, such + as a screen display or a screenshot. Neither you nor anyone at your + direction shall do any of the following acts: + + a. Rent the Software; + + b. Sell the Software; + + c. Lease or lend the Software; + + d. Offer the Software on a pay-per-play basis; + + e. Distribute the Software for money or any other + consideration; or + + f. In any other manner and through any medium + whatsoever commercially exploit the Software or use + the Software for any commercial purpose. + + 3. Additional Prohibited Uses. Neither you, nor anyone at your + direction, shall take the following action in regard to the + Software, or any portion thereof, such as a screen display or + a screenshot: + + a. Modify, disassemble, reverse engineer or decompile + the Software; + + b. Translate the Software; + + c. Reproduce the Software; + + d. Publicly display the Software; or + + e. Prepare derivative works based upon the Software. + + 4. Use of Other Material is Prohibited. Use, in any manner, of + the trademarks, such as Quake(tm) and the NIN(r) logo, logos, symbols, + art work, images, screen displays or screenshots, sound effects, music, + and other such material contained within, generated by or relating to + the Software is prohibited. + + 5. Restrictions Apply to Third Parties. The prohibitions and + restrictions described herein apply to anyone in possession of + the Software. + + 6. Permitted Distribution. So long as this Agreement + accompanies the Software at all times, ID grants to Providers the + limited right to distribute, free of charge, except normal access + fees, and by electronic means only, the Software; provided, however, + the Software must be so electronically distributed only in a + compressed format. The term "Providers," as used in the foregoing + sentence, shall mean persons whose business it is to provide + services on the Internet, on commercial online networks, or on the + BBS. Anyone who receives the Software from a Provider shall be + limited to all the terms and conditions of this Agreement. Further, + ID grants to you, the end-user, the limited right to distribute, + free of charge only, the Software as a whole. + + 7. Copyright. The Software is owned by ID and is protected by + United States copyright laws and international treaty provisions. + You must treat the Software like any other copyrighted material, + except that you may make copies of the Software to give to other + persons. You may not charge or receive any consideration from any + other person for the receipt or use of the Software. You agree to + use your best efforts to see that any user of the Software licensed + hereunder complies with this Agreement. + + 8. Limited Warranty. ID warrants that if properly installed and + operated on a computer for which it is designed, the Software will + perform substantially in accordance with its designed purpose for a + period of ninety (90) days from the date the Software is first + obtained by an end-user. ID's entire liability and your exclusive + remedy shall be, at ID's option, either (a) return of the retail + price paid, if any, or (b) repair or replacement of the Software + that does not meet ID's Limited Warranty. To make a warranty claim, + return the Software to the point of purchase, accompanied by proof + of purchase, your name, your address, and a statement of defect, or + return the Software with the above information to ID. This Limited + Warranty is void if failure of the Software has resulted in whole + or in part from accident, abuse, misapplication or violation of this + Agreement. Any replacement Software will be warranted for the + remainder of the original warranty period or thirty (30) days, + whichever is longer. This warranty allocates risks of product + failure between Licensee and ID. ID's product pricing reflects this + allocation of risk and the limitations of liability contained in + this warranty. + + 9. NO OTHER WARRANTIES. ID DISCLAIMS ALL OTHER WARRANTIES, + EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A pARTICULAR PURPOSE + WITH RESPECT TO THE SOFTWARE AND THE ACCOMPANYING WRITTEN MATERIALS, + IF ANY. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. YOU + MAY HAVE OTHERS WHICH VARY FROM JURISDICTION TO JURISDICTION. ID + DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE + UNINTERRUPTED, ERROR FREE OR MEET LICENSEE'S SPECIFIC REQUIREMENTS. + THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS + WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES, + DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE + MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF + OF ID. ADDITIONAL STATEMENTS SUCH AS DEALER ADVERTISING OR + PRESENTATIONS, WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE WARRANTIES + BY ID AND SHOULD NOT BE RELIED UPON. + + 10. Exclusive Remedies. You agree that your exclusive remedy + against ID, its affiliates, contractors, suppliers, and agents for + loss or damage caused by any defect or failure in the Software + regardless of the form of action, whether in contract,tort, + including negligence, strict liability or otherwise, shall be the + return of the retail purchase price paid, if any, or replacement of + the Software. This Agreement shall be construed in accordance with + and governed by the laws of the State of Texas. Copyright and other + proprietary matters will be governed by United States laws and + international treaties. IN ANY CASE, ID SHALL NOT BE LIABLE FOR LOSS + OF DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, + CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES ARISING FROM BREACH + OF WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, OR OTHER LEGAL THEORY + EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do + not allow the exclusion or limitation of incidental or consequential + damages, so the above limitation or exclusion may not apply to you. + + 11. General Provisions. Neither this Agreement nor any part or + portion hereof shall be assigned or sublicensed, except as described + herein. Should any provision of this Agreement be held to be void, + invalid, unenforceable or illegal by a court, the validity and + enforceability of the other provisions shall not be affected thereby. + If any provision is determined to be unenforceable, you agree to a + modification of such provision to provide for enforcement of the + provision's intent, to the extent permitted by applicable law. Failure + of a party to enforce any provision of this Agreement shall not + constitute or be construed as a waiver of such provision or of the + right to enforce such provision. If you fail to comply with any terms + of this Agreement, YOUR LICENSE IS AUTOMATICALLY TERMINATED. + + YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, YOU UNDERSTAND + THIS AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE INSTALLATION + OF THE SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING + OR COPYING THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, YOU AGREE TO + BE BOUND BY THIS AGREEMENT'S TERMS AND CONDITIONS. YOU FURTHER + AGREE THAT, EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID AND + YOU, THIS AGREEMENT IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE + RIGHTS AND LIABILITIES OF THE PARTIES. THIS AGREEMENT SUPERSEDES + ALL PRIOR ORAL AGREEMENTS, PROPOSALS OR UNDERSTANDINGS, AND ANY + OTHER COMMUNICATIONS BETWEEN ID AND YOU RELATING TO THE SUBJECT + MATTER OF THIS AGREEMENT. + +June 21, 1996 + +SHAREWARE VERSION: QUAKE LIMITED USE SOFTWARE LICENSE AGREEMENT +(DWC:dw:3406.0024:DWC\doc:1163) diff --git a/WinQuake/debugi386/bin/id1/config.cfg b/WinQuake/debugi386/bin/id1/config.cfg deleted file mode 100644 index 2773495..0000000 --- a/WinQuake/debugi386/bin/id1/config.cfg +++ /dev/null @@ -1,84 +0,0 @@ -bind "TAB" "+showscores " -bind "ENTER" "+jump " -bind "ESCAPE" "togglemenu " -bind "SPACE" "+jump " -bind "+" "sizeup " -bind "," "+moveleft " -bind "-" "sizedown " -bind "." "+moveright " -bind "/" "impulse 10 " -bind "0" "impulse 0 " -bind "1" "impulse 1 " -bind "2" "impulse 2 " -bind "3" "impulse 3 " -bind "4" "impulse 4 " -bind "5" "impulse 5 " -bind "6" "impulse 6 " -bind "7" "impulse 7 " -bind "8" "impulse 8 " -bind "=" "sizeup " -bind "\" "+mlook " -bind "`" "toggleconsole " -bind "a" "+lookup " -bind "c" "+movedown " -bind "d" "+moveup " -bind "t" "messagemode " -bind "z" "+lookdown " -bind "~" "toggleconsole " -bind "UPARROW" "+forward " -bind "DOWNARROW" "+back " -bind "LEFTARROW" "+left " -bind "RIGHTARROW" "+right " -bind "ALT" "+strafe " -bind "CTRL" "+attack " -bind "SHIFT" "+speed " -bind "F1" "help " -bind "F2" "menu_save " -bind "F3" "menu_load " -bind "F4" "menu_options " -bind "F5" "menu_multiplayer " -bind "F6" "echo Quicksaving...; wait; save quick " -bind "F9" "echo Quickloading...; wait; load quick " -bind "F10" "quit " -bind "F11" "zoom_in " -bind "F12" "screenshot " -bind "INS" "+klook " -bind "DEL" "+lookdown " -bind "PGDN" "+lookup " -bind "END" "centerview " -bind "MOUSE1" "+attack " -bind "MOUSE2" "+forward " -bind "MOUSE3" "+mlook " -bind "PAUSE" "pause " -m_side "0.8" -m_forward "1" -m_yaw "0.022" -m_pitch "0.022000" -sensitivity "3.500000" -lookstrafe "0.000000" -lookspring "0.000000" -cl_backspeed "200.000000" -cl_forwardspeed "200.000000" -_cl_color "85.000000" -_cl_name "steph" -_snd_mixahead "0.1" -bgmvolume "1.000000" -volume "1.000000" -gl_triplebuffer "1" -viewsize "110.000000" -_config_modem_hangup "AT H" -_config_modem_init "" -_config_modem_clear "ATZ" -_config_modem_dialtype "T" -_config_com_modem "1.000000" -_config_com_baud "57600.000000" -_config_com_irq "4.000000" -_config_com_port "1016.000000" -gl_subdivide_size "128" -saved4 "0" -saved3 "0" -saved2 "0" -saved1 "0" -savedgamecfg "0" -gamma "0.650000" -crosshair "0" diff --git a/WinQuake/debugi386/bin/id1/glquake/armor.ms2 b/WinQuake/debugi386/bin/id1/glquake/armor.ms2 deleted file mode 100644 index 8610113..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/armor.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/backpack.ms2 b/WinQuake/debugi386/bin/id1/glquake/backpack.ms2 deleted file mode 100644 index ad635e7..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/backpack.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/bolt.ms2 b/WinQuake/debugi386/bin/id1/glquake/bolt.ms2 deleted file mode 100644 index fc24033..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/bolt.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/bolt2.ms2 b/WinQuake/debugi386/bin/id1/glquake/bolt2.ms2 deleted file mode 100644 index 09b432d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/bolt2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/bolt3.ms2 b/WinQuake/debugi386/bin/id1/glquake/bolt3.ms2 deleted file mode 100644 index 09b432d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/bolt3.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/demon.ms2 b/WinQuake/debugi386/bin/id1/glquake/demon.ms2 deleted file mode 100644 index 8c2fc95..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/demon.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/eyes.ms2 b/WinQuake/debugi386/bin/id1/glquake/eyes.ms2 deleted file mode 100644 index 46bebe0..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/eyes.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/flame.ms2 b/WinQuake/debugi386/bin/id1/glquake/flame.ms2 deleted file mode 100644 index 53ac0ea..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/flame.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/flame2.ms2 b/WinQuake/debugi386/bin/id1/glquake/flame2.ms2 deleted file mode 100644 index 70821fd..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/flame2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/g_nail.ms2 b/WinQuake/debugi386/bin/id1/glquake/g_nail.ms2 deleted file mode 100644 index 183abbb..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/g_nail.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/g_rock.ms2 b/WinQuake/debugi386/bin/id1/glquake/g_rock.ms2 deleted file mode 100644 index 52193c6..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/g_rock.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/g_shot.ms2 b/WinQuake/debugi386/bin/id1/glquake/g_shot.ms2 deleted file mode 100644 index 7552234..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/g_shot.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/gib1.ms2 b/WinQuake/debugi386/bin/id1/glquake/gib1.ms2 deleted file mode 100644 index e6761c6..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/gib1.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/gib2.ms2 b/WinQuake/debugi386/bin/id1/glquake/gib2.ms2 deleted file mode 100644 index 57687bb..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/gib2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/gib3.ms2 b/WinQuake/debugi386/bin/id1/glquake/gib3.ms2 deleted file mode 100644 index 30dc77d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/gib3.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/grenade.ms2 b/WinQuake/debugi386/bin/id1/glquake/grenade.ms2 deleted file mode 100644 index 9e3f074..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/grenade.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/h_demon.ms2 b/WinQuake/debugi386/bin/id1/glquake/h_demon.ms2 deleted file mode 100644 index 00669e9..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/h_demon.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/h_ogre.ms2 b/WinQuake/debugi386/bin/id1/glquake/h_ogre.ms2 deleted file mode 100644 index a69beb6..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/h_ogre.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/h_player.ms2 b/WinQuake/debugi386/bin/id1/glquake/h_player.ms2 deleted file mode 100644 index 6a83d4d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/h_player.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/h_wizard.ms2 b/WinQuake/debugi386/bin/id1/glquake/h_wizard.ms2 deleted file mode 100644 index 6c54860..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/h_wizard.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/h_zombie.ms2 b/WinQuake/debugi386/bin/id1/glquake/h_zombie.ms2 deleted file mode 100644 index 2c87240..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/h_zombie.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/invisibl.ms2 b/WinQuake/debugi386/bin/id1/glquake/invisibl.ms2 deleted file mode 100644 index dd58d5e..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/invisibl.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/lavaball.ms2 b/WinQuake/debugi386/bin/id1/glquake/lavaball.ms2 deleted file mode 100644 index 8e88ecc..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/lavaball.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/missile.ms2 b/WinQuake/debugi386/bin/id1/glquake/missile.ms2 deleted file mode 100644 index 5cbb423..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/missile.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/ogre.ms2 b/WinQuake/debugi386/bin/id1/glquake/ogre.ms2 deleted file mode 100644 index cd0a083..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/ogre.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/player.ms2 b/WinQuake/debugi386/bin/id1/glquake/player.ms2 deleted file mode 100644 index fbe097d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/player.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/s_spike.ms2 b/WinQuake/debugi386/bin/id1/glquake/s_spike.ms2 deleted file mode 100644 index fa2ed46..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/s_spike.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/spike.ms2 b/WinQuake/debugi386/bin/id1/glquake/spike.ms2 deleted file mode 100644 index fa2ed46..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/spike.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_axe.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_axe.ms2 deleted file mode 100644 index 2309a3d..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_axe.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_light.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_light.ms2 deleted file mode 100644 index d130885..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_light.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_nail.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_nail.ms2 deleted file mode 100644 index 45e8747..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_nail.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_nail2.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_nail2.ms2 deleted file mode 100644 index 75df88c..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_nail2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_rock.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_rock.ms2 deleted file mode 100644 index e7c9d26..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_rock.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_rock2.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_rock2.ms2 deleted file mode 100644 index fb9cf69..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_rock2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_shot.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_shot.ms2 deleted file mode 100644 index 760f08c..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_shot.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/v_shot2.ms2 b/WinQuake/debugi386/bin/id1/glquake/v_shot2.ms2 deleted file mode 100644 index 4c821a7..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/v_shot2.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/w_g_key.ms2 b/WinQuake/debugi386/bin/id1/glquake/w_g_key.ms2 deleted file mode 100644 index 6aec3ef..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/w_g_key.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/w_spike.ms2 b/WinQuake/debugi386/bin/id1/glquake/w_spike.ms2 deleted file mode 100644 index 9c748d1..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/w_spike.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/wizard.ms2 b/WinQuake/debugi386/bin/id1/glquake/wizard.ms2 deleted file mode 100644 index 124bf2b..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/wizard.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/zom_gib.ms2 b/WinQuake/debugi386/bin/id1/glquake/zom_gib.ms2 deleted file mode 100644 index dad69cd..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/zom_gib.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/glquake/zombie.ms2 b/WinQuake/debugi386/bin/id1/glquake/zombie.ms2 deleted file mode 100644 index fb11b92..0000000 Binary files a/WinQuake/debugi386/bin/id1/glquake/zombie.ms2 and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/pak0.pak b/WinQuake/debugi386/bin/id1/pak0.pak deleted file mode 100644 index 51c1b99..0000000 Binary files a/WinQuake/debugi386/bin/id1/pak0.pak and /dev/null differ diff --git a/WinQuake/debugi386/bin/id1/pak1.pak b/WinQuake/debugi386/bin/id1/pak1.pak deleted file mode 100644 index b8634b5..0000000 Binary files a/WinQuake/debugi386/bin/id1/pak1.pak and /dev/null differ diff --git a/WinQuake/dos_v2.c b/WinQuake/dos_v2.c index 3adf2cb..d10dea3 100644 --- a/WinQuake/dos_v2.c +++ b/WinQuake/dos_v2.c @@ -1,257 +1,257 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include -#include -#include -#include -#include -#include -#include -// #include -#include - -#include "dosisms.h" - -_go32_dpmi_registers hmm; - -// globals -regs_t regs; -void (*dos_error_func)(char *msg, ...); - -static unsigned conventional_memory = -1; - -__dpmi_regs callback_regs; - -void map_in_conventional_memory(void) -{ - if (conventional_memory == -1) - { - if (__djgpp_nearptr_enable()) - { - conventional_memory = __djgpp_conventional_base; - } - } -} - -unsigned int ptr2real(void *ptr) -{ - map_in_conventional_memory(); - return (int)ptr - conventional_memory; -} - -void *real2ptr(unsigned int real) -{ - map_in_conventional_memory(); - return (void *) (real + conventional_memory); -} - -void *far2ptr(unsigned int farptr) -{ - return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff)); -} - -unsigned int ptr2far(void *ptr) -{ - return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf); -} - -int dos_inportb(int port) -{ - return inportb(port); -} - -int dos_inportw(int port) -{ - return inportw(port); -} - -void dos_outportb(int port, int val) -{ - outportb(port, val); -} - -void dos_outportw(int port, int val) -{ - outportw(port, val); -} - -void dos_irqenable(void) -{ - enable(); -} - -void dos_irqdisable(void) -{ - disable(); -} - -// -// Returns 0 on success -// - -int dos_int86(int vec) -{ - int rc; - regs.x.ss = regs.x.sp = 0; - rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) ®s); - return rc || (regs.x.flags & 1); -} - -int dos_int386(int vec, regs_t *inregs, regs_t *outregs) -{ - int rc; - memcpy(outregs, inregs, sizeof(regs_t)); - outregs->x.ss = outregs->x.sp = 0; - rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs); - return rc || (outregs->x.flags & 1); -} - -// -// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep -// the seginfo structure around for when you free the mem. -// - -static _go32_dpmi_seginfo seginfo[10]; - -void *dos_getmemory(int size) -{ - - int rc; - _go32_dpmi_seginfo info; - static int firsttime=1; - int i; - - if (firsttime) - { - memset(seginfo, 0, sizeof(seginfo)); - firsttime = 0; - } - - info.size = (size+15) / 16; - rc = _go32_dpmi_allocate_dos_memory(&info); - if (rc) - return 0; - - for (i=0;i<10;i++) - if (!seginfo[i].rm_segment) break; - seginfo[i] = info; - return real2ptr((int) info.rm_segment << 4); - -} - -void dos_freememory(void *ptr) -{ - - int i; - int segment; - - segment = ptr2real(ptr) >> 4; - for (i=0 ; i<10 ; i++) - if (seginfo[i].rm_segment == segment) - { - _go32_dpmi_free_dos_memory(&seginfo[i]); - seginfo[i].rm_segment = 0; - break; - } - -} - -static struct handlerhistory_s -{ - int intr; - _go32_dpmi_seginfo pm_oldvec; -} handlerhistory[4]; - -static int handlercount=0; - -void dos_registerintr(int intr, void (*handler)(void)) -{ - _go32_dpmi_seginfo info; - struct handlerhistory_s *oldstuff; - - oldstuff = &handlerhistory[handlercount]; - -// remember old handler - _go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec); - oldstuff->intr = intr; - - info.pm_offset = (int) handler; - _go32_dpmi_allocate_iret_wrapper(&info); - -// set new protected mode handler - _go32_dpmi_set_protected_mode_interrupt_vector(intr, &info); - - handlercount++; - -} - -void dos_restoreintr(int intr) -{ - - int i; - struct handlerhistory_s *oldstuff; - -// find and reinstall previous interrupt - for (i=0 ; iintr == intr) - { - _go32_dpmi_set_protected_mode_interrupt_vector(intr, - &oldstuff->pm_oldvec); - oldstuff->intr = -1; - break; - } - } - -} - -void dos_usleep(int usecs) -{ - usleep(usecs); -} - -int dos_getheapsize(void) -{ - return _go32_dpmi_remaining_physical_memory(); -} - -int dos_lockmem(void *addr, int size) -{ - __dpmi_meminfo info; - info.address = (long) addr + __djgpp_base_address; - info.size = size; - if (__dpmi_lock_linear_region(&info)) - return __dpmi_error; - else - return 0; -} - -int dos_unlockmem(void *addr, int size) -{ - __dpmi_meminfo info; - info.address = (long) addr + __djgpp_base_address; - info.size = size; - if (__dpmi_unlock_linear_region(&info)) - return __dpmi_error; - else - return 0; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include +#include +#include +#include +#include +#include +#include +// #include +#include + +#include "dosisms.h" + +_go32_dpmi_registers hmm; + +// globals +regs_t regs; +void (*dos_error_func)(char *msg, ...); + +static unsigned conventional_memory = -1; + +__dpmi_regs callback_regs; + +void map_in_conventional_memory(void) +{ + if (conventional_memory == -1) + { + if (__djgpp_nearptr_enable()) + { + conventional_memory = __djgpp_conventional_base; + } + } +} + +unsigned int ptr2real(void *ptr) +{ + map_in_conventional_memory(); + return (int)ptr - conventional_memory; +} + +void *real2ptr(unsigned int real) +{ + map_in_conventional_memory(); + return (void *) (real + conventional_memory); +} + +void *far2ptr(unsigned int farptr) +{ + return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff)); +} + +unsigned int ptr2far(void *ptr) +{ + return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf); +} + +int dos_inportb(int port) +{ + return inportb(port); +} + +int dos_inportw(int port) +{ + return inportw(port); +} + +void dos_outportb(int port, int val) +{ + outportb(port, val); +} + +void dos_outportw(int port, int val) +{ + outportw(port, val); +} + +void dos_irqenable(void) +{ + enable(); +} + +void dos_irqdisable(void) +{ + disable(); +} + +// +// Returns 0 on success +// + +int dos_int86(int vec) +{ + int rc; + regs.x.ss = regs.x.sp = 0; + rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) ®s); + return rc || (regs.x.flags & 1); +} + +int dos_int386(int vec, regs_t *inregs, regs_t *outregs) +{ + int rc; + memcpy(outregs, inregs, sizeof(regs_t)); + outregs->x.ss = outregs->x.sp = 0; + rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs); + return rc || (outregs->x.flags & 1); +} + +// +// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep +// the seginfo structure around for when you free the mem. +// + +static _go32_dpmi_seginfo seginfo[10]; + +void *dos_getmemory(int size) +{ + + int rc; + _go32_dpmi_seginfo info; + static int firsttime=1; + int i; + + if (firsttime) + { + memset(seginfo, 0, sizeof(seginfo)); + firsttime = 0; + } + + info.size = (size+15) / 16; + rc = _go32_dpmi_allocate_dos_memory(&info); + if (rc) + return 0; + + for (i=0;i<10;i++) + if (!seginfo[i].rm_segment) break; + seginfo[i] = info; + return real2ptr((int) info.rm_segment << 4); + +} + +void dos_freememory(void *ptr) +{ + + int i; + int segment; + + segment = ptr2real(ptr) >> 4; + for (i=0 ; i<10 ; i++) + if (seginfo[i].rm_segment == segment) + { + _go32_dpmi_free_dos_memory(&seginfo[i]); + seginfo[i].rm_segment = 0; + break; + } + +} + +static struct handlerhistory_s +{ + int intr; + _go32_dpmi_seginfo pm_oldvec; +} handlerhistory[4]; + +static int handlercount=0; + +void dos_registerintr(int intr, void (*handler)(void)) +{ + _go32_dpmi_seginfo info; + struct handlerhistory_s *oldstuff; + + oldstuff = &handlerhistory[handlercount]; + +// remember old handler + _go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec); + oldstuff->intr = intr; + + info.pm_offset = (int) handler; + _go32_dpmi_allocate_iret_wrapper(&info); + +// set new protected mode handler + _go32_dpmi_set_protected_mode_interrupt_vector(intr, &info); + + handlercount++; + +} + +void dos_restoreintr(int intr) +{ + + int i; + struct handlerhistory_s *oldstuff; + +// find and reinstall previous interrupt + for (i=0 ; iintr == intr) + { + _go32_dpmi_set_protected_mode_interrupt_vector(intr, + &oldstuff->pm_oldvec); + oldstuff->intr = -1; + break; + } + } + +} + +void dos_usleep(int usecs) +{ + usleep(usecs); +} + +int dos_getheapsize(void) +{ + return _go32_dpmi_remaining_physical_memory(); +} + +int dos_lockmem(void *addr, int size) +{ + __dpmi_meminfo info; + info.address = (long) addr + __djgpp_base_address; + info.size = size; + if (__dpmi_lock_linear_region(&info)) + return __dpmi_error; + else + return 0; +} + +int dos_unlockmem(void *addr, int size) +{ + __dpmi_meminfo info; + info.address = (long) addr + __djgpp_base_address; + info.size = size; + if (__dpmi_unlock_linear_region(&info)) + return __dpmi_error; + else + return 0; +} + diff --git a/WinQuake/dosisms.h b/WinQuake/dosisms.h index 7f12268..ad85835 100644 --- a/WinQuake/dosisms.h +++ b/WinQuake/dosisms.h @@ -1,100 +1,100 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// -// dosisms.h: I'd call it dos.h, but the name's taken -// - -#ifndef _DOSISMS_H_ -#define _DOSISMS_H_ - -int dos_lockmem(void *addr, int size); -int dos_unlockmem(void *addr, int size); - -typedef union { - struct { - unsigned long edi; - unsigned long esi; - unsigned long ebp; - unsigned long res; - unsigned long ebx; - unsigned long edx; - unsigned long ecx; - unsigned long eax; - } d; - struct { - unsigned short di, di_hi; - unsigned short si, si_hi; - unsigned short bp, bp_hi; - unsigned short res, res_hi; - unsigned short bx, bx_hi; - unsigned short dx, dx_hi; - unsigned short cx, cx_hi; - unsigned short ax, ax_hi; - unsigned short flags; - unsigned short es; - unsigned short ds; - unsigned short fs; - unsigned short gs; - unsigned short ip; - unsigned short cs; - unsigned short sp; - unsigned short ss; - } x; - struct { - unsigned char edi[4]; - unsigned char esi[4]; - unsigned char ebp[4]; - unsigned char res[4]; - unsigned char bl, bh, ebx_b2, ebx_b3; - unsigned char dl, dh, edx_b2, edx_b3; - unsigned char cl, ch, ecx_b2, ecx_b3; - unsigned char al, ah, eax_b2, eax_b3; - } h; -} regs_t; - -unsigned int ptr2real(void *ptr); -void *real2ptr(unsigned int real); -void *far2ptr(unsigned int farptr); -unsigned int ptr2far(void *ptr); - -int dos_inportb(int port); -int dos_inportw(int port); -void dos_outportb(int port, int val); -void dos_outportw(int port, int val); - -void dos_irqenable(void); -void dos_irqdisable(void); -void dos_registerintr(int intr, void (*handler)(void)); -void dos_restoreintr(int intr); - -int dos_int86(int vec); - -void *dos_getmemory(int size); -void dos_freememory(void *ptr); - -void dos_usleep(int usecs); - -int dos_getheapsize(void); - -extern regs_t regs; - -#endif // _DOSISMS_H_ - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// dosisms.h: I'd call it dos.h, but the name's taken +// + +#ifndef _DOSISMS_H_ +#define _DOSISMS_H_ + +int dos_lockmem(void *addr, int size); +int dos_unlockmem(void *addr, int size); + +typedef union { + struct { + unsigned long edi; + unsigned long esi; + unsigned long ebp; + unsigned long res; + unsigned long ebx; + unsigned long edx; + unsigned long ecx; + unsigned long eax; + } d; + struct { + unsigned short di, di_hi; + unsigned short si, si_hi; + unsigned short bp, bp_hi; + unsigned short res, res_hi; + unsigned short bx, bx_hi; + unsigned short dx, dx_hi; + unsigned short cx, cx_hi; + unsigned short ax, ax_hi; + unsigned short flags; + unsigned short es; + unsigned short ds; + unsigned short fs; + unsigned short gs; + unsigned short ip; + unsigned short cs; + unsigned short sp; + unsigned short ss; + } x; + struct { + unsigned char edi[4]; + unsigned char esi[4]; + unsigned char ebp[4]; + unsigned char res[4]; + unsigned char bl, bh, ebx_b2, ebx_b3; + unsigned char dl, dh, edx_b2, edx_b3; + unsigned char cl, ch, ecx_b2, ecx_b3; + unsigned char al, ah, eax_b2, eax_b3; + } h; +} regs_t; + +unsigned int ptr2real(void *ptr); +void *real2ptr(unsigned int real); +void *far2ptr(unsigned int farptr); +unsigned int ptr2far(void *ptr); + +int dos_inportb(int port); +int dos_inportw(int port); +void dos_outportb(int port, int val); +void dos_outportw(int port, int val); + +void dos_irqenable(void); +void dos_irqdisable(void); +void dos_registerintr(int intr, void (*handler)(void)); +void dos_restoreintr(int intr); + +int dos_int86(int vec); + +void *dos_getmemory(int size); +void dos_freememory(void *ptr); + +void dos_usleep(int usecs); + +int dos_getheapsize(void); + +extern regs_t regs; + +#endif // _DOSISMS_H_ + diff --git a/WinQuake/draw.c b/WinQuake/draw.c index 00ee0b4..39114f5 100644 --- a/WinQuake/draw.c +++ b/WinQuake/draw.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // draw.c -- this is the only file outside the refresh that touches the // vid buffer diff --git a/WinQuake/draw.h b/WinQuake/draw.h index 5055b65..e54999c 100644 --- a/WinQuake/draw.h +++ b/WinQuake/draw.h @@ -1,40 +1,40 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// draw.h -- these are the only functions outside the refresh allowed -// to touch the vid buffer - -extern qpic_t *draw_disc; // also used on sbar - -void Draw_Init (void); -void Draw_Character (int x, int y, int num); -void Draw_DebugChar (char num); -void Draw_Pic (int x, int y, qpic_t *pic); -void Draw_TransPic (int x, int y, qpic_t *pic); -void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation); -void Draw_ConsoleBackground (int lines); -void Draw_BeginDisc (void); -void Draw_EndDisc (void); -void Draw_TileClear (int x, int y, int w, int h); -void Draw_Fill (int x, int y, int w, int h, int c); -void Draw_FadeScreen (void); -void Draw_String (int x, int y, char *str); -qpic_t *Draw_PicFromWad (char *name); -qpic_t *Draw_CachePic (char *path); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// draw.h -- these are the only functions outside the refresh allowed +// to touch the vid buffer + +extern qpic_t *draw_disc; // also used on sbar + +void Draw_Init (void); +void Draw_Character (int x, int y, int num); +void Draw_DebugChar (char num); +void Draw_Pic (int x, int y, qpic_t *pic); +void Draw_TransPic (int x, int y, qpic_t *pic); +void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation); +void Draw_ConsoleBackground (int lines); +void Draw_BeginDisc (void); +void Draw_EndDisc (void); +void Draw_TileClear (int x, int y, int w, int h); +void Draw_Fill (int x, int y, int w, int h, int c); +void Draw_FadeScreen (void); +void Draw_String (int x, int y, char *str); +qpic_t *Draw_PicFromWad (char *name); +qpic_t *Draw_CachePic (char *path); diff --git a/WinQuake/dxsdk/SDK/INC/D3D.H b/WinQuake/dxsdk/SDK/INC/D3D.H index 8a67742..d908a59 100644 --- a/WinQuake/dxsdk/SDK/INC/D3D.H +++ b/WinQuake/dxsdk/SDK/INC/D3D.H @@ -1,392 +1,392 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3d.h - * Content: Direct3D include file - * - ***************************************************************************/ - -#ifndef _D3D_H_ -#define _D3D_H_ - -#include - -#ifdef _WIN32 -#define COM_NO_WINDOWS_H -#include -#else -#include "d3dcom.h" -#endif - -#ifdef _WIN32 -#define D3DAPI WINAPI -#else -#define D3DAPI -#endif - -/* - * Interface IID's - */ -#if defined( _WIN32 ) && !defined( _NO_COM) -DEFINE_GUID( IID_IDirect3D, 0x3BBA0080,0x2421,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 ); -DEFINE_GUID( IID_IDirect3DTexture, 0x2CDCD9E0,0x25A0,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 ); -DEFINE_GUID( IID_IDirect3DLight, 0x4417C142,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); -DEFINE_GUID( IID_IDirect3DMaterial, 0x4417C144,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); -DEFINE_GUID( IID_IDirect3DExecuteBuffer,0x4417C145,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); -DEFINE_GUID( IID_IDirect3DViewport, 0x4417C146,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Data structures - */ -#ifdef __cplusplus - -/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ -struct IDirect3D; -struct IDirect3DDevice; -struct IDirect3DExecuteBuffer; -struct IDirect3DLight; -struct IDirect3DMaterial; -struct IDirect3DTexture; -struct IDirect3DViewport; -typedef struct IDirect3D *LPDIRECT3D; -typedef struct IDirect3DDevice *LPDIRECT3DDEVICE; -typedef struct IDirect3DExecuteBuffer *LPDIRECT3DEXECUTEBUFFER; -typedef struct IDirect3DLight *LPDIRECT3DLIGHT; -typedef struct IDirect3DMaterial *LPDIRECT3DMATERIAL; -typedef struct IDirect3DTexture *LPDIRECT3DTEXTURE; -typedef struct IDirect3DViewport *LPDIRECT3DVIEWPORT; - -#else - -typedef struct IDirect3D *LPDIRECT3D; -typedef struct IDirect3DDevice *LPDIRECT3DDEVICE; -typedef struct IDirect3DExecuteBuffer *LPDIRECT3DEXECUTEBUFFER; -typedef struct IDirect3DLight *LPDIRECT3DLIGHT; -typedef struct IDirect3DMaterial *LPDIRECT3DMATERIAL; -typedef struct IDirect3DTexture *LPDIRECT3DTEXTURE; -typedef struct IDirect3DViewport *LPDIRECT3DVIEWPORT; - -#endif - -#include "d3dtypes.h" -#include "d3dcaps.h" - -/* - * IDirect3D - */ -#undef INTERFACE -#define INTERFACE IDirect3D -DECLARE_INTERFACE_(IDirect3D, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3D methods ***/ - STDMETHOD(Initialize) (THIS_ REFIID) PURE; - STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK, LPVOID) PURE; - STDMETHOD(CreateLight) (THIS_ LPDIRECT3DLIGHT*, IUnknown*) PURE; - STDMETHOD(CreateMaterial) (THIS_ LPDIRECT3DMATERIAL*, IUnknown*) PURE; - STDMETHOD(CreateViewport) (THIS_ LPDIRECT3DVIEWPORT*, IUnknown*) PURE; - STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3D_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3D_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3D_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3D_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirect3D_EnumDevices(p, a, b) (p)->lpVtbl->EnumDevices(p, a, b) -#define IDirect3D_CreateLight(p, a, b) (p)->lpVtbl->CreateLight(p, a, b) -#define IDirect3D_CreateMaterial(p, a, b) (p)->lpVtbl->CreateMaterial(p, a, b) -#define IDirect3D_CreateViewport(p, a, b) (p)->lpVtbl->CreateViewport(p, a, b) -#define IDirect3D_FindDevice(p, a, b) (p)->lpVtbl->FindDevice(p, a, b) -#endif - -/* - * IDirect3DDevice - */ -#undef INTERFACE -#define INTERFACE IDirect3DDevice -DECLARE_INTERFACE_(IDirect3DDevice, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DDevice methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3D, LPGUID, LPD3DDEVICEDESC) PURE; - STDMETHOD(GetCaps) (THIS_ LPD3DDEVICEDESC, LPD3DDEVICEDESC) PURE; - STDMETHOD(SwapTextureHandles) (THIS_ LPDIRECT3DTEXTURE, LPDIRECT3DTEXTURE) PURE; - STDMETHOD(CreateExecuteBuffer) (THIS_ LPD3DEXECUTEBUFFERDESC, LPDIRECT3DEXECUTEBUFFER*, IUnknown*) PURE; - STDMETHOD(GetStats) (THIS_ LPD3DSTATS) PURE; - STDMETHOD(Execute) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD) PURE; - STDMETHOD(AddViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE; - STDMETHOD(DeleteViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE; - STDMETHOD(NextViewport) (THIS_ LPDIRECT3DVIEWPORT, LPDIRECT3DVIEWPORT*, DWORD) PURE; - STDMETHOD(Pick) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD, LPD3DRECT) PURE; - STDMETHOD(GetPickRecords)(THIS_ LPDWORD, LPD3DPICKRECORD) PURE; - STDMETHOD(EnumTextureFormats) (THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK, LPVOID) PURE; - STDMETHOD(CreateMatrix) (THIS_ LPD3DMATRIXHANDLE) PURE; - STDMETHOD(SetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE; - STDMETHOD(GetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE; - STDMETHOD(DeleteMatrix) (THIS_ D3DMATRIXHANDLE) PURE; - STDMETHOD_(HRESULT, BeginScene) (THIS) PURE; - STDMETHOD_(HRESULT, EndScene) (THIS) PURE; - STDMETHOD(GetDirect3D) (THIS_ LPDIRECT3D*) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DDevice_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DDevice_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DDevice_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DDevice_Initialize(p, a, b, c) (p)->lpVtbl->Initialize(p, a, b, c) -#define IDirect3DDevice_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) -#define IDirect3DDevice_SwapTextureHandles(p, a, b) (p)->lpVtbl->SwapTextureHandles(p, a, b) -#define IDirect3DDevice_CreateExecuteBuffer(p, a, b, c) (p)->lpVtbl->ExecuteBuffer(p, a, b, c) -#define IDirect3DDevice_GetStats(p, a) (p)->lpVtbl->CreateViewport(p, a) -#define IDirect3DDevice_Execute(p, a, b, c) (p)->lpVtbl->Execute(p, a, b, c) -#define IDirect3DDevice_AddViewport(p, a) (p)->lpVtbl->AddViewport(p, a) -#define IDirect3DDevice_DeleteViewport(p, a) (p)->lpVtbl->DeleteViewport(p, a) -#define IDirect3DDevice_NextViewport(p, a, b) (p)->lpVtbl->NextViewport(p, a, b) -#define IDirect3DDevice_Pick(p, a, b, c, d) (p)->lpVtbl->Pick(p, a, b, c, d) -#define IDirect3DDevice_GetPickRecords(p, a, b) (p)->lpVtbl->GetPickRecords(p, a, b) -#define IDirect3DDevice_EnumTextureFormats(p, a, b) (p)->lpVtbl->EnumTextureFormats(p, a, b) -#define IDirect3DDevice_CreateMatrix(p, a) (p)->lpVtbl->CreateMatrix(p, a) -#define IDirect3DDevice_SetMatrix(p, a, b) (p)->lpVtbl->SetMatrix(p, a, b) -#define IDirect3DDevice_GetMatrix(p, a, b) (p)->lpVtbl->GetMatrix(p, a, b) -#define IDirect3DDevice_DeleteMatrix(p, a) (p)->lpVtbl->DeleteMatrix(p, a) -#define IDirect3DDevice_BeginScene(p) (p)->lpVtbl->BeginScene(p) -#define IDirect3DDevice_EndScene(p) (p)->lpVtbl->EndScene(p) -#define IDirect3DDevice_GetDirect3D(p, a) (p)->lpVtbl->GetDirect3D(p, a) -#endif - -/* - * IDirect3DExecuteBuffer - */ -#undef INTERFACE -#define INTERFACE IDirect3DExecuteBuffer -DECLARE_INTERFACE_(IDirect3DExecuteBuffer, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DExecuteBuffer methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPD3DEXECUTEBUFFERDESC) PURE; - STDMETHOD(Lock) (THIS_ LPD3DEXECUTEBUFFERDESC) PURE; - STDMETHOD_(HRESULT, Unlock) (THIS) PURE; - STDMETHOD(SetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE; - STDMETHOD(GetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE; - STDMETHOD(Validate) (THIS_ LPDWORD, LPD3DVALIDATECALLBACK, LPVOID, DWORD) PURE; - STDMETHOD(Optimize) (THIS_ DWORD) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DExecuteBuffer_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DExecuteBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DExecuteBuffer_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DExecuteBuffer_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) -#define IDirect3DExecuteBuffer_Lock(p, a) (p)->lpVtbl->Lock(p, a) -#define IDirect3DExecuteBuffer_Unlock(p, a) (p)->lpVtbl->Unlock(p) -#define IDirect3DExecuteBuffer_SetExecuteData(p, a) (p)->lpVtbl->SetExecuteData(p, a) -#define IDirect3DExecuteBuffer_Validate(p, a, b, c, d) (p)->lpVtbl->Validata(p, a, b, c, d) -#endif - -/* - * Flags for execute buffer calls - */ -#define D3DNEXT_NEXT 0x00000001l -#define D3DNEXT_HEAD 0x00000002l -#define D3DNEXT_TAIL 0x00000004l - -/* - * IDirect3DLight - */ -#undef INTERFACE -#define INTERFACE IDirect3DLight -DECLARE_INTERFACE_(IDirect3DLight, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DLight methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; - STDMETHOD(SetLight) (THIS_ LPD3DLIGHT) PURE; - STDMETHOD(GetLight) (THIS_ LPD3DLIGHT) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DLight_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DLight_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DLight_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DLight_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirect3DLight_SetLight(p, a) (p)->lpVtbl->SetLight(p, a) -#define IDirect3DLight_GetLight(p, a) (p)->lpVtbl->GetLight(p, a) -#endif - -/* - * IDirect3DMaterial - */ -#undef INTERFACE -#define INTERFACE IDirect3DMaterial -DECLARE_INTERFACE_(IDirect3DMaterial, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DMaterial methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; - STDMETHOD(SetMaterial) (THIS_ LPD3DMATERIAL) PURE; - STDMETHOD(GetMaterial) (THIS_ LPD3DMATERIAL) PURE; - STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DMATERIALHANDLE) PURE; - STDMETHOD_(HRESULT, Reserve) (THIS) PURE; - STDMETHOD_(HRESULT, Unreserve) (THIS) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DMaterial_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DMaterial_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DMaterial_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DMaterial_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirect3DMaterial_SetMaterial(p, a) (p)->lpVtbl->SetLight(p, a) -#define IDirect3DMaterial_GetMaterial(p, a) (p)->lpVtbl->GetLight(p, a) -#define IDirect3DMaterial_GetHandle(p, a, b) (p)->lpVtbl->GetHandle(p, a, b) -#define IDirect3DMaterial_Reserve(p) (p)->lpVtbl->Reserve(p) -#define IDirect3DMaterial_Unreserve(p) (p)->lpVtbl->Unreserve(p) -#endif - -/* - * IDirect3DTexture - */ -#undef INTERFACE -#define INTERFACE IDirect3DTexture -DECLARE_INTERFACE_(IDirect3DTexture, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DTexture methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPDIRECTDRAWSURFACE) PURE; - STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DTEXTUREHANDLE) PURE; - STDMETHOD(PaletteChanged) (THIS_ DWORD, DWORD) PURE; - STDMETHOD(Load) (THIS_ LPDIRECT3DTEXTURE) PURE; - STDMETHOD_(HRESULT, Unload) (THIS) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DTexture_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DTexture_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DTexture_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DTexture_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) -#define IDirect3DTexture_GetHandle(p, a, b) (p)->lpVtbl->GetHandle(p, a, b) -#define IDirect3DTexture_PaletteChanged(p, a, b) (p)->lpVtbl->PaletteChanged(p, a, b) -#define IDirect3DTexture_Load(p, a) (p)->lpVtbl->Load(p, a) -#define IDirect3DTexture_Unload(p) (p)->lpVtbl->Unload(p) -#endif - -/* - * IDirect3DViewport - */ -#undef INTERFACE -#define INTERFACE IDirect3DViewport -DECLARE_INTERFACE_(IDirect3DViewport, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; - STDMETHOD_(ULONG, AddRef) (THIS) PURE; - STDMETHOD_(ULONG, Release) (THIS) PURE; - /*** IDirect3DViewport methods ***/ - STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; - STDMETHOD(GetViewport) (THIS_ LPD3DVIEWPORT) PURE; - STDMETHOD(SetViewport) (THIS_ LPD3DVIEWPORT) PURE; - STDMETHOD(TransformVertices) (THIS_ DWORD, LPD3DTRANSFORMDATA, DWORD, LPDWORD) PURE; - STDMETHOD(LightElements) (THIS_ DWORD, LPD3DLIGHTDATA) PURE; - STDMETHOD(SetBackground) (THIS_ D3DMATERIALHANDLE) PURE; - STDMETHOD(GetBackground) (THIS_ LPD3DMATERIALHANDLE, LPBOOL) PURE; - STDMETHOD(SetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE) PURE; - STDMETHOD(GetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE*, LPBOOL) PURE; - STDMETHOD(Clear) (THIS_ DWORD, LPD3DRECT, DWORD) PURE; - STDMETHOD(AddLight) (THIS_ LPDIRECT3DLIGHT) PURE; - STDMETHOD(DeleteLight) (THIS_ LPDIRECT3DLIGHT) PURE; - STDMETHOD(NextLight) (THIS_ LPDIRECT3DLIGHT, LPDIRECT3DLIGHT*, DWORD) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirect3DViewport_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirect3DViewport_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirect3DViewport_Release(p) (p)->lpVtbl->Release(p) -#define IDirect3DViewport_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirect3DViewport_GetViewport(p, a) (p)->lpVtbl->GetViewport(p, a) -#define IDirect3DViewport_SetViewport(p, a) (p)->lpVtbl->SetViewport(p, a) -#define IDirect3DViewport_TransformVertices(p, a, b, c, d) (p)->lpVtbl->TransformVertices(p, a, b, c, d) -#define IDirect3DViewport_LightElements(p, a, b) (p)->lpVtbl->LightElements(p, a, b) -#define IDirect3DViewport_SetBackground(p, a) (p)->lpVtbl->SetBackground(p, a) -#define IDirect3DViewport_GetBackground(p, a, b) (p)->lpVtbl->GetBackground(p, a, b) -#define IDirect3DViewport_Clear(p, a, b, c) (p)->lpVtbl->Clear(p, a, b, c) -#define IDirect3DViewport_AddLight(p, a) (p)->lpVtbl->AddLight(p, a) -#define IDirect3DViewport_DeleteLight(p, a) (p)->lpVtbl->DeleteLight(p, a) -#define IDirect3DViewport_NextLight(p, a, b, c) (p)->lpVtbl->NextLight(p, a, b, c) -#endif - -/* - * Direct3D Errors - * DirectDraw error codes are used when errors not specified here. - */ -#define D3D_OK DD_OK -#define D3DERR_BADMAJORVERSION MAKE_DDHRESULT(700) -#define D3DERR_BADMINORVERSION MAKE_DDHRESULT(701) - -#define D3DERR_EXECUTE_CREATE_FAILED MAKE_DDHRESULT(710) -#define D3DERR_EXECUTE_DESTROY_FAILED MAKE_DDHRESULT(711) -#define D3DERR_EXECUTE_LOCK_FAILED MAKE_DDHRESULT(712) -#define D3DERR_EXECUTE_UNLOCK_FAILED MAKE_DDHRESULT(713) -#define D3DERR_EXECUTE_LOCKED MAKE_DDHRESULT(714) -#define D3DERR_EXECUTE_NOT_LOCKED MAKE_DDHRESULT(715) - -#define D3DERR_EXECUTE_FAILED MAKE_DDHRESULT(716) -#define D3DERR_EXECUTE_CLIPPED_FAILED MAKE_DDHRESULT(717) - -#define D3DERR_TEXTURE_NO_SUPPORT MAKE_DDHRESULT(720) -#define D3DERR_TEXTURE_CREATE_FAILED MAKE_DDHRESULT(721) -#define D3DERR_TEXTURE_DESTROY_FAILED MAKE_DDHRESULT(722) -#define D3DERR_TEXTURE_LOCK_FAILED MAKE_DDHRESULT(723) -#define D3DERR_TEXTURE_UNLOCK_FAILED MAKE_DDHRESULT(724) -#define D3DERR_TEXTURE_LOAD_FAILED MAKE_DDHRESULT(725) -#define D3DERR_TEXTURE_SWAP_FAILED MAKE_DDHRESULT(726) -#define D3DERR_TEXTURE_LOCKED MAKE_DDHRESULT(727) -#define D3DERR_TEXTURE_NOT_LOCKED MAKE_DDHRESULT(728) -#define D3DERR_TEXTURE_GETSURF_FAILED MAKE_DDHRESULT(729) - -#define D3DERR_MATRIX_CREATE_FAILED MAKE_DDHRESULT(730) -#define D3DERR_MATRIX_DESTROY_FAILED MAKE_DDHRESULT(731) -#define D3DERR_MATRIX_SETDATA_FAILED MAKE_DDHRESULT(732) -#define D3DERR_MATRIX_GETDATA_FAILED MAKE_DDHRESULT(733) -#define D3DERR_SETVIEWPORTDATA_FAILED MAKE_DDHRESULT(734) - -#define D3DERR_MATERIAL_CREATE_FAILED MAKE_DDHRESULT(740) -#define D3DERR_MATERIAL_DESTROY_FAILED MAKE_DDHRESULT(741) -#define D3DERR_MATERIAL_SETDATA_FAILED MAKE_DDHRESULT(742) -#define D3DERR_MATERIAL_GETDATA_FAILED MAKE_DDHRESULT(743) - -#define D3DERR_LIGHT_SET_FAILED MAKE_DDHRESULT(750) - -#define D3DERR_SCENE_IN_SCENE MAKE_DDHRESULT(760) -#define D3DERR_SCENE_NOT_IN_SCENE MAKE_DDHRESULT(761) -#define D3DERR_SCENE_BEGIN_FAILED MAKE_DDHRESULT(762) -#define D3DERR_SCENE_END_FAILED MAKE_DDHRESULT(763) - -#ifdef __cplusplus -}; -#endif - -#endif /* _D3D_H_ */ +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3d.h + * Content: Direct3D include file + * + ***************************************************************************/ + +#ifndef _D3D_H_ +#define _D3D_H_ + +#include + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#else +#include "d3dcom.h" +#endif + +#ifdef _WIN32 +#define D3DAPI WINAPI +#else +#define D3DAPI +#endif + +/* + * Interface IID's + */ +#if defined( _WIN32 ) && !defined( _NO_COM) +DEFINE_GUID( IID_IDirect3D, 0x3BBA0080,0x2421,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 ); +DEFINE_GUID( IID_IDirect3DTexture, 0x2CDCD9E0,0x25A0,0x11CF,0xA3,0x1A,0x00,0xAA,0x00,0xB9,0x33,0x56 ); +DEFINE_GUID( IID_IDirect3DLight, 0x4417C142,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); +DEFINE_GUID( IID_IDirect3DMaterial, 0x4417C144,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); +DEFINE_GUID( IID_IDirect3DExecuteBuffer,0x4417C145,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); +DEFINE_GUID( IID_IDirect3DViewport, 0x4417C146,0x33AD,0x11CF,0x81,0x6F,0x00,0x00,0xC0,0x20,0x15,0x6E ); +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Data structures + */ +#ifdef __cplusplus + +/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ +struct IDirect3D; +struct IDirect3DDevice; +struct IDirect3DExecuteBuffer; +struct IDirect3DLight; +struct IDirect3DMaterial; +struct IDirect3DTexture; +struct IDirect3DViewport; +typedef struct IDirect3D *LPDIRECT3D; +typedef struct IDirect3DDevice *LPDIRECT3DDEVICE; +typedef struct IDirect3DExecuteBuffer *LPDIRECT3DEXECUTEBUFFER; +typedef struct IDirect3DLight *LPDIRECT3DLIGHT; +typedef struct IDirect3DMaterial *LPDIRECT3DMATERIAL; +typedef struct IDirect3DTexture *LPDIRECT3DTEXTURE; +typedef struct IDirect3DViewport *LPDIRECT3DVIEWPORT; + +#else + +typedef struct IDirect3D *LPDIRECT3D; +typedef struct IDirect3DDevice *LPDIRECT3DDEVICE; +typedef struct IDirect3DExecuteBuffer *LPDIRECT3DEXECUTEBUFFER; +typedef struct IDirect3DLight *LPDIRECT3DLIGHT; +typedef struct IDirect3DMaterial *LPDIRECT3DMATERIAL; +typedef struct IDirect3DTexture *LPDIRECT3DTEXTURE; +typedef struct IDirect3DViewport *LPDIRECT3DVIEWPORT; + +#endif + +#include "d3dtypes.h" +#include "d3dcaps.h" + +/* + * IDirect3D + */ +#undef INTERFACE +#define INTERFACE IDirect3D +DECLARE_INTERFACE_(IDirect3D, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3D methods ***/ + STDMETHOD(Initialize) (THIS_ REFIID) PURE; + STDMETHOD(EnumDevices)(THIS_ LPD3DENUMDEVICESCALLBACK, LPVOID) PURE; + STDMETHOD(CreateLight) (THIS_ LPDIRECT3DLIGHT*, IUnknown*) PURE; + STDMETHOD(CreateMaterial) (THIS_ LPDIRECT3DMATERIAL*, IUnknown*) PURE; + STDMETHOD(CreateViewport) (THIS_ LPDIRECT3DVIEWPORT*, IUnknown*) PURE; + STDMETHOD(FindDevice)(THIS_ LPD3DFINDDEVICESEARCH, LPD3DFINDDEVICERESULT) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3D_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3D_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3D_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3D_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirect3D_EnumDevices(p, a, b) (p)->lpVtbl->EnumDevices(p, a, b) +#define IDirect3D_CreateLight(p, a, b) (p)->lpVtbl->CreateLight(p, a, b) +#define IDirect3D_CreateMaterial(p, a, b) (p)->lpVtbl->CreateMaterial(p, a, b) +#define IDirect3D_CreateViewport(p, a, b) (p)->lpVtbl->CreateViewport(p, a, b) +#define IDirect3D_FindDevice(p, a, b) (p)->lpVtbl->FindDevice(p, a, b) +#endif + +/* + * IDirect3DDevice + */ +#undef INTERFACE +#define INTERFACE IDirect3DDevice +DECLARE_INTERFACE_(IDirect3DDevice, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DDevice methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3D, LPGUID, LPD3DDEVICEDESC) PURE; + STDMETHOD(GetCaps) (THIS_ LPD3DDEVICEDESC, LPD3DDEVICEDESC) PURE; + STDMETHOD(SwapTextureHandles) (THIS_ LPDIRECT3DTEXTURE, LPDIRECT3DTEXTURE) PURE; + STDMETHOD(CreateExecuteBuffer) (THIS_ LPD3DEXECUTEBUFFERDESC, LPDIRECT3DEXECUTEBUFFER*, IUnknown*) PURE; + STDMETHOD(GetStats) (THIS_ LPD3DSTATS) PURE; + STDMETHOD(Execute) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD) PURE; + STDMETHOD(AddViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE; + STDMETHOD(DeleteViewport) (THIS_ LPDIRECT3DVIEWPORT) PURE; + STDMETHOD(NextViewport) (THIS_ LPDIRECT3DVIEWPORT, LPDIRECT3DVIEWPORT*, DWORD) PURE; + STDMETHOD(Pick) (THIS_ LPDIRECT3DEXECUTEBUFFER, LPDIRECT3DVIEWPORT, DWORD, LPD3DRECT) PURE; + STDMETHOD(GetPickRecords)(THIS_ LPDWORD, LPD3DPICKRECORD) PURE; + STDMETHOD(EnumTextureFormats) (THIS_ LPD3DENUMTEXTUREFORMATSCALLBACK, LPVOID) PURE; + STDMETHOD(CreateMatrix) (THIS_ LPD3DMATRIXHANDLE) PURE; + STDMETHOD(SetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE; + STDMETHOD(GetMatrix) (THIS_ D3DMATRIXHANDLE, LPD3DMATRIX) PURE; + STDMETHOD(DeleteMatrix) (THIS_ D3DMATRIXHANDLE) PURE; + STDMETHOD_(HRESULT, BeginScene) (THIS) PURE; + STDMETHOD_(HRESULT, EndScene) (THIS) PURE; + STDMETHOD(GetDirect3D) (THIS_ LPDIRECT3D*) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DDevice_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DDevice_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DDevice_Initialize(p, a, b, c) (p)->lpVtbl->Initialize(p, a, b, c) +#define IDirect3DDevice_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) +#define IDirect3DDevice_SwapTextureHandles(p, a, b) (p)->lpVtbl->SwapTextureHandles(p, a, b) +#define IDirect3DDevice_CreateExecuteBuffer(p, a, b, c) (p)->lpVtbl->ExecuteBuffer(p, a, b, c) +#define IDirect3DDevice_GetStats(p, a) (p)->lpVtbl->CreateViewport(p, a) +#define IDirect3DDevice_Execute(p, a, b, c) (p)->lpVtbl->Execute(p, a, b, c) +#define IDirect3DDevice_AddViewport(p, a) (p)->lpVtbl->AddViewport(p, a) +#define IDirect3DDevice_DeleteViewport(p, a) (p)->lpVtbl->DeleteViewport(p, a) +#define IDirect3DDevice_NextViewport(p, a, b) (p)->lpVtbl->NextViewport(p, a, b) +#define IDirect3DDevice_Pick(p, a, b, c, d) (p)->lpVtbl->Pick(p, a, b, c, d) +#define IDirect3DDevice_GetPickRecords(p, a, b) (p)->lpVtbl->GetPickRecords(p, a, b) +#define IDirect3DDevice_EnumTextureFormats(p, a, b) (p)->lpVtbl->EnumTextureFormats(p, a, b) +#define IDirect3DDevice_CreateMatrix(p, a) (p)->lpVtbl->CreateMatrix(p, a) +#define IDirect3DDevice_SetMatrix(p, a, b) (p)->lpVtbl->SetMatrix(p, a, b) +#define IDirect3DDevice_GetMatrix(p, a, b) (p)->lpVtbl->GetMatrix(p, a, b) +#define IDirect3DDevice_DeleteMatrix(p, a) (p)->lpVtbl->DeleteMatrix(p, a) +#define IDirect3DDevice_BeginScene(p) (p)->lpVtbl->BeginScene(p) +#define IDirect3DDevice_EndScene(p) (p)->lpVtbl->EndScene(p) +#define IDirect3DDevice_GetDirect3D(p, a) (p)->lpVtbl->GetDirect3D(p, a) +#endif + +/* + * IDirect3DExecuteBuffer + */ +#undef INTERFACE +#define INTERFACE IDirect3DExecuteBuffer +DECLARE_INTERFACE_(IDirect3DExecuteBuffer, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DExecuteBuffer methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPD3DEXECUTEBUFFERDESC) PURE; + STDMETHOD(Lock) (THIS_ LPD3DEXECUTEBUFFERDESC) PURE; + STDMETHOD_(HRESULT, Unlock) (THIS) PURE; + STDMETHOD(SetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE; + STDMETHOD(GetExecuteData) (THIS_ LPD3DEXECUTEDATA) PURE; + STDMETHOD(Validate) (THIS_ LPDWORD, LPD3DVALIDATECALLBACK, LPVOID, DWORD) PURE; + STDMETHOD(Optimize) (THIS_ DWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DExecuteBuffer_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DExecuteBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DExecuteBuffer_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DExecuteBuffer_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) +#define IDirect3DExecuteBuffer_Lock(p, a) (p)->lpVtbl->Lock(p, a) +#define IDirect3DExecuteBuffer_Unlock(p, a) (p)->lpVtbl->Unlock(p) +#define IDirect3DExecuteBuffer_SetExecuteData(p, a) (p)->lpVtbl->SetExecuteData(p, a) +#define IDirect3DExecuteBuffer_Validate(p, a, b, c, d) (p)->lpVtbl->Validata(p, a, b, c, d) +#endif + +/* + * Flags for execute buffer calls + */ +#define D3DNEXT_NEXT 0x00000001l +#define D3DNEXT_HEAD 0x00000002l +#define D3DNEXT_TAIL 0x00000004l + +/* + * IDirect3DLight + */ +#undef INTERFACE +#define INTERFACE IDirect3DLight +DECLARE_INTERFACE_(IDirect3DLight, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DLight methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; + STDMETHOD(SetLight) (THIS_ LPD3DLIGHT) PURE; + STDMETHOD(GetLight) (THIS_ LPD3DLIGHT) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DLight_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DLight_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DLight_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DLight_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirect3DLight_SetLight(p, a) (p)->lpVtbl->SetLight(p, a) +#define IDirect3DLight_GetLight(p, a) (p)->lpVtbl->GetLight(p, a) +#endif + +/* + * IDirect3DMaterial + */ +#undef INTERFACE +#define INTERFACE IDirect3DMaterial +DECLARE_INTERFACE_(IDirect3DMaterial, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DMaterial methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; + STDMETHOD(SetMaterial) (THIS_ LPD3DMATERIAL) PURE; + STDMETHOD(GetMaterial) (THIS_ LPD3DMATERIAL) PURE; + STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DMATERIALHANDLE) PURE; + STDMETHOD_(HRESULT, Reserve) (THIS) PURE; + STDMETHOD_(HRESULT, Unreserve) (THIS) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DMaterial_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DMaterial_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DMaterial_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DMaterial_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirect3DMaterial_SetMaterial(p, a) (p)->lpVtbl->SetLight(p, a) +#define IDirect3DMaterial_GetMaterial(p, a) (p)->lpVtbl->GetLight(p, a) +#define IDirect3DMaterial_GetHandle(p, a, b) (p)->lpVtbl->GetHandle(p, a, b) +#define IDirect3DMaterial_Reserve(p) (p)->lpVtbl->Reserve(p) +#define IDirect3DMaterial_Unreserve(p) (p)->lpVtbl->Unreserve(p) +#endif + +/* + * IDirect3DTexture + */ +#undef INTERFACE +#define INTERFACE IDirect3DTexture +DECLARE_INTERFACE_(IDirect3DTexture, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DTexture methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3DDEVICE, LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(GetHandle) (THIS_ LPDIRECT3DDEVICE, LPD3DTEXTUREHANDLE) PURE; + STDMETHOD(PaletteChanged) (THIS_ DWORD, DWORD) PURE; + STDMETHOD(Load) (THIS_ LPDIRECT3DTEXTURE) PURE; + STDMETHOD_(HRESULT, Unload) (THIS) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DTexture_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DTexture_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DTexture_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DTexture_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) +#define IDirect3DTexture_GetHandle(p, a, b) (p)->lpVtbl->GetHandle(p, a, b) +#define IDirect3DTexture_PaletteChanged(p, a, b) (p)->lpVtbl->PaletteChanged(p, a, b) +#define IDirect3DTexture_Load(p, a) (p)->lpVtbl->Load(p, a) +#define IDirect3DTexture_Unload(p) (p)->lpVtbl->Unload(p) +#endif + +/* + * IDirect3DViewport + */ +#undef INTERFACE +#define INTERFACE IDirect3DViewport +DECLARE_INTERFACE_(IDirect3DViewport, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID* ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + /*** IDirect3DViewport methods ***/ + STDMETHOD(Initialize) (THIS_ LPDIRECT3D) PURE; + STDMETHOD(GetViewport) (THIS_ LPD3DVIEWPORT) PURE; + STDMETHOD(SetViewport) (THIS_ LPD3DVIEWPORT) PURE; + STDMETHOD(TransformVertices) (THIS_ DWORD, LPD3DTRANSFORMDATA, DWORD, LPDWORD) PURE; + STDMETHOD(LightElements) (THIS_ DWORD, LPD3DLIGHTDATA) PURE; + STDMETHOD(SetBackground) (THIS_ D3DMATERIALHANDLE) PURE; + STDMETHOD(GetBackground) (THIS_ LPD3DMATERIALHANDLE, LPBOOL) PURE; + STDMETHOD(SetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(GetBackgroundDepth) (THIS_ LPDIRECTDRAWSURFACE*, LPBOOL) PURE; + STDMETHOD(Clear) (THIS_ DWORD, LPD3DRECT, DWORD) PURE; + STDMETHOD(AddLight) (THIS_ LPDIRECT3DLIGHT) PURE; + STDMETHOD(DeleteLight) (THIS_ LPDIRECT3DLIGHT) PURE; + STDMETHOD(NextLight) (THIS_ LPDIRECT3DLIGHT, LPDIRECT3DLIGHT*, DWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DViewport_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirect3DViewport_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DViewport_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DViewport_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirect3DViewport_GetViewport(p, a) (p)->lpVtbl->GetViewport(p, a) +#define IDirect3DViewport_SetViewport(p, a) (p)->lpVtbl->SetViewport(p, a) +#define IDirect3DViewport_TransformVertices(p, a, b, c, d) (p)->lpVtbl->TransformVertices(p, a, b, c, d) +#define IDirect3DViewport_LightElements(p, a, b) (p)->lpVtbl->LightElements(p, a, b) +#define IDirect3DViewport_SetBackground(p, a) (p)->lpVtbl->SetBackground(p, a) +#define IDirect3DViewport_GetBackground(p, a, b) (p)->lpVtbl->GetBackground(p, a, b) +#define IDirect3DViewport_Clear(p, a, b, c) (p)->lpVtbl->Clear(p, a, b, c) +#define IDirect3DViewport_AddLight(p, a) (p)->lpVtbl->AddLight(p, a) +#define IDirect3DViewport_DeleteLight(p, a) (p)->lpVtbl->DeleteLight(p, a) +#define IDirect3DViewport_NextLight(p, a, b, c) (p)->lpVtbl->NextLight(p, a, b, c) +#endif + +/* + * Direct3D Errors + * DirectDraw error codes are used when errors not specified here. + */ +#define D3D_OK DD_OK +#define D3DERR_BADMAJORVERSION MAKE_DDHRESULT(700) +#define D3DERR_BADMINORVERSION MAKE_DDHRESULT(701) + +#define D3DERR_EXECUTE_CREATE_FAILED MAKE_DDHRESULT(710) +#define D3DERR_EXECUTE_DESTROY_FAILED MAKE_DDHRESULT(711) +#define D3DERR_EXECUTE_LOCK_FAILED MAKE_DDHRESULT(712) +#define D3DERR_EXECUTE_UNLOCK_FAILED MAKE_DDHRESULT(713) +#define D3DERR_EXECUTE_LOCKED MAKE_DDHRESULT(714) +#define D3DERR_EXECUTE_NOT_LOCKED MAKE_DDHRESULT(715) + +#define D3DERR_EXECUTE_FAILED MAKE_DDHRESULT(716) +#define D3DERR_EXECUTE_CLIPPED_FAILED MAKE_DDHRESULT(717) + +#define D3DERR_TEXTURE_NO_SUPPORT MAKE_DDHRESULT(720) +#define D3DERR_TEXTURE_CREATE_FAILED MAKE_DDHRESULT(721) +#define D3DERR_TEXTURE_DESTROY_FAILED MAKE_DDHRESULT(722) +#define D3DERR_TEXTURE_LOCK_FAILED MAKE_DDHRESULT(723) +#define D3DERR_TEXTURE_UNLOCK_FAILED MAKE_DDHRESULT(724) +#define D3DERR_TEXTURE_LOAD_FAILED MAKE_DDHRESULT(725) +#define D3DERR_TEXTURE_SWAP_FAILED MAKE_DDHRESULT(726) +#define D3DERR_TEXTURE_LOCKED MAKE_DDHRESULT(727) +#define D3DERR_TEXTURE_NOT_LOCKED MAKE_DDHRESULT(728) +#define D3DERR_TEXTURE_GETSURF_FAILED MAKE_DDHRESULT(729) + +#define D3DERR_MATRIX_CREATE_FAILED MAKE_DDHRESULT(730) +#define D3DERR_MATRIX_DESTROY_FAILED MAKE_DDHRESULT(731) +#define D3DERR_MATRIX_SETDATA_FAILED MAKE_DDHRESULT(732) +#define D3DERR_MATRIX_GETDATA_FAILED MAKE_DDHRESULT(733) +#define D3DERR_SETVIEWPORTDATA_FAILED MAKE_DDHRESULT(734) + +#define D3DERR_MATERIAL_CREATE_FAILED MAKE_DDHRESULT(740) +#define D3DERR_MATERIAL_DESTROY_FAILED MAKE_DDHRESULT(741) +#define D3DERR_MATERIAL_SETDATA_FAILED MAKE_DDHRESULT(742) +#define D3DERR_MATERIAL_GETDATA_FAILED MAKE_DDHRESULT(743) + +#define D3DERR_LIGHT_SET_FAILED MAKE_DDHRESULT(750) + +#define D3DERR_SCENE_IN_SCENE MAKE_DDHRESULT(760) +#define D3DERR_SCENE_NOT_IN_SCENE MAKE_DDHRESULT(761) +#define D3DERR_SCENE_BEGIN_FAILED MAKE_DDHRESULT(762) +#define D3DERR_SCENE_END_FAILED MAKE_DDHRESULT(763) + +#ifdef __cplusplus +}; +#endif + +#endif /* _D3D_H_ */ diff --git a/WinQuake/dxsdk/SDK/INC/D3DCAPS.H b/WinQuake/dxsdk/SDK/INC/D3DCAPS.H index 60a44c1..0c21ee7 100644 --- a/WinQuake/dxsdk/SDK/INC/D3DCAPS.H +++ b/WinQuake/dxsdk/SDK/INC/D3DCAPS.H @@ -1,290 +1,290 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3dcaps.h - * Content: Direct3D capabilities include file - * - ***************************************************************************/ - -#ifndef _D3DCAPS_H -#define _D3DCAPS_H - -/* - * Pull in DirectDraw include file automatically: - */ -#include - -#pragma pack(4) - -/* Description of capabilities of transform */ - -typedef struct _D3DTRANSFORMCAPS { - DWORD dwSize; - DWORD dwCaps; -} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS; - -#define D3DTRANSFORMCAPS_CLIP 0x00000001L /* Will clip whilst transforming */ - -/* Description of capabilities of lighting */ - -typedef struct _D3DLIGHTINGCAPS { - DWORD dwSize; - DWORD dwCaps; /* Lighting caps */ - DWORD dwLightingModel; /* Lighting model - RGB or mono */ - DWORD dwNumLights; /* Number of lights that can be handled */ -} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS; - -#define D3DLIGHTINGMODEL_RGB 0x00000001L -#define D3DLIGHTINGMODEL_MONO 0x00000002L - -#define D3DLIGHTCAPS_POINT 0x00000001L /* Point lights supported */ -#define D3DLIGHTCAPS_SPOT 0x00000002L /* Spot lights supported */ -#define D3DLIGHTCAPS_DIRECTIONAL 0x00000004L /* Directional lights supported */ -#define D3DLIGHTCAPS_PARALLELPOINT 0x00000008L /* Parallel point lights supported */ -#define D3DLIGHTCAPS_GLSPOT 0x00000010L /* GL syle spot lights supported */ - -/* Description of capabilities for each primitive type */ - -typedef struct _D3DPrimCaps { - DWORD dwSize; - DWORD dwMiscCaps; /* Capability flags */ - DWORD dwRasterCaps; - DWORD dwZCmpCaps; - DWORD dwSrcBlendCaps; - DWORD dwDestBlendCaps; - DWORD dwAlphaCmpCaps; - DWORD dwShadeCaps; - DWORD dwTextureCaps; - DWORD dwTextureFilterCaps; - DWORD dwTextureBlendCaps; - DWORD dwTextureAddressCaps; - DWORD dwStippleWidth; /* maximum width and height of */ - DWORD dwStippleHeight; /* of supported stipple (up to 32x32) */ -} D3DPRIMCAPS, *LPD3DPRIMCAPS; - -/* D3DPRIMCAPS dwMiscCaps */ - -#define D3DPMISCCAPS_MASKPLANES 0x00000001L -#define D3DPMISCCAPS_MASKZ 0x00000002L -#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L -#define D3DPMISCCAPS_CONFORMANT 0x00000008L -#define D3DPMISCCAPS_CULLNONE 0x00000010L -#define D3DPMISCCAPS_CULLCW 0x00000020L -#define D3DPMISCCAPS_CULLCCW 0x00000040L - -/* D3DPRIMCAPS dwRasterCaps */ - -#define D3DPRASTERCAPS_DITHER 0x00000001L -#define D3DPRASTERCAPS_ROP2 0x00000002L -#define D3DPRASTERCAPS_XOR 0x00000004L -#define D3DPRASTERCAPS_PAT 0x00000008L -#define D3DPRASTERCAPS_ZTEST 0x00000010L -#define D3DPRASTERCAPS_SUBPIXEL 0x00000020L -#define D3DPRASTERCAPS_SUBPIXELX 0x00000040L -#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L -#define D3DPRASTERCAPS_FOGTABLE 0x00000100L -#define D3DPRASTERCAPS_STIPPLE 0x00000200L - -/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */ - -#define D3DPCMPCAPS_NEVER 0x00000001L -#define D3DPCMPCAPS_LESS 0x00000002L -#define D3DPCMPCAPS_EQUAL 0x00000004L -#define D3DPCMPCAPS_LESSEQUAL 0x00000008L -#define D3DPCMPCAPS_GREATER 0x00000010L -#define D3DPCMPCAPS_NOTEQUAL 0x00000020L -#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L -#define D3DPCMPCAPS_ALWAYS 0x00000080L - -/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */ - -#define D3DPBLENDCAPS_ZERO 0x00000001L -#define D3DPBLENDCAPS_ONE 0x00000002L -#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L -#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L -#define D3DPBLENDCAPS_SRCALPHA 0x00000010L -#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L -#define D3DPBLENDCAPS_DESTALPHA 0x00000040L -#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L -#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L -#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L -#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L -#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L -#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L - -/* D3DPRIMCAPS dwShadeCaps */ - -#define D3DPSHADECAPS_COLORFLATMONO 0x00000001L -#define D3DPSHADECAPS_COLORFLATRGB 0x00000002L -#define D3DPSHADECAPS_COLORGOURAUDMONO 0x00000004L -#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L -#define D3DPSHADECAPS_COLORPHONGMONO 0x00000010L -#define D3DPSHADECAPS_COLORPHONGRGB 0x00000020L - -#define D3DPSHADECAPS_SPECULARFLATMONO 0x00000040L -#define D3DPSHADECAPS_SPECULARFLATRGB 0x00000080L -#define D3DPSHADECAPS_SPECULARGOURAUDMONO 0x00000100L -#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L -#define D3DPSHADECAPS_SPECULARPHONGMONO 0x00000400L -#define D3DPSHADECAPS_SPECULARPHONGRGB 0x00000800L - -#define D3DPSHADECAPS_ALPHAFLATBLEND 0x00001000L -#define D3DPSHADECAPS_ALPHAFLATSTIPPLED 0x00002000L -#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L -#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED 0x00008000L -#define D3DPSHADECAPS_ALPHAPHONGBLEND 0x00010000L -#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED 0x00020000L - -#define D3DPSHADECAPS_FOGFLAT 0x00040000L -#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L -#define D3DPSHADECAPS_FOGPHONG 0x00100000L - -/* D3DPRIMCAPS dwTextureCaps */ - -#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L -#define D3DPTEXTURECAPS_POW2 0x00000002L -#define D3DPTEXTURECAPS_ALPHA 0x00000004L -#define D3DPTEXTURECAPS_TRANSPARENCY 0x00000008L -#define D3DPTEXTURECAPS_BORDER 0x00000010L -#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L - -/* D3DPRIMCAPS dwTextureFilterCaps */ - -#define D3DPTFILTERCAPS_NEAREST 0x00000001L -#define D3DPTFILTERCAPS_LINEAR 0x00000002L -#define D3DPTFILTERCAPS_MIPNEAREST 0x00000004L -#define D3DPTFILTERCAPS_MIPLINEAR 0x00000008L -#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L -#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L - -/* D3DPRIMCAPS dwTextureBlendCaps */ - -#define D3DPTBLENDCAPS_DECAL 0x00000001L -#define D3DPTBLENDCAPS_MODULATE 0x00000002L -#define D3DPTBLENDCAPS_DECALALPHA 0x00000004L -#define D3DPTBLENDCAPS_MODULATEALPHA 0x00000008L -#define D3DPTBLENDCAPS_DECALMASK 0x00000010L -#define D3DPTBLENDCAPS_MODULATEMASK 0x00000020L -#define D3DPTBLENDCAPS_COPY 0x00000040L - -/* D3DPRIMCAPS dwTextureAddressCaps */ -#define D3DPTADDRESSCAPS_WRAP 0x00000001L -#define D3DPTADDRESSCAPS_MIRROR 0x00000002L -#define D3DPTADDRESSCAPS_CLAMP 0x00000004L - -/* - * Description for a device. - * This is used to describe a device that is to be created or to query - * the current device. - */ -typedef struct _D3DDeviceDesc { - DWORD dwSize; /* Size of D3DDEVICEDESC structure */ - DWORD dwFlags; /* Indicates which fields have valid data */ - D3DCOLORMODEL dcmColorModel; /* Color model of device */ - DWORD dwDevCaps; /* Capabilities of device */ - D3DTRANSFORMCAPS dtcTransformCaps; /* Capabilities of transform */ - BOOL bClipping; /* Device can do 3D clipping */ - D3DLIGHTINGCAPS dlcLightingCaps; /* Capabilities of lighting */ - D3DPRIMCAPS dpcLineCaps; - D3DPRIMCAPS dpcTriCaps; - DWORD dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */ - DWORD dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */ - DWORD dwMaxBufferSize; /* Maximum execute buffer size */ - DWORD dwMaxVertexCount; /* Maximum vertex count */ -} D3DDEVICEDESC, *LPD3DDEVICEDESC; - -typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID); - -/* D3DDEVICEDESC dwFlags indicating valid fields */ - -#define D3DDD_COLORMODEL 0x00000001L /* dcmColorModel is valid */ -#define D3DDD_DEVCAPS 0x00000002L /* dwDevCaps is valid */ -#define D3DDD_TRANSFORMCAPS 0x00000004L /* dtcTransformCaps is valid */ -#define D3DDD_LIGHTINGCAPS 0x00000008L /* dlcLightingCaps is valid */ -#define D3DDD_BCLIPPING 0x00000010L /* bClipping is valid */ -#define D3DDD_LINECAPS 0x00000020L /* dpcLineCaps is valid */ -#define D3DDD_TRICAPS 0x00000040L /* dpcTriCaps is valid */ -#define D3DDD_DEVICERENDERBITDEPTH 0x00000080L /* dwDeviceRenderBitDepth is valid */ -#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */ -#define D3DDD_MAXBUFFERSIZE 0x00000200L /* dwMaxBufferSize is valid */ -#define D3DDD_MAXVERTEXCOUNT 0x00000400L /* dwMaxVertexCount is valid */ - -/* D3DDEVICEDESC dwDevCaps flags */ - -#define D3DDEVCAPS_FLOATTLVERTEX 0x00000001L /* Device accepts floating point */ - /* for post-transform vertex data */ -#define D3DDEVCAPS_SORTINCREASINGZ 0x00000002L /* Device needs data sorted for increasing Z*/ -#define D3DDEVCAPS_SORTDECREASINGZ 0X00000004L /* Device needs data sorted for decreasing Z*/ -#define D3DDEVCAPS_SORTEXACT 0x00000008L /* Device needs data sorted exactly */ - -#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ -#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */ -#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ -#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ -#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ -#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ - -#define D3DFDS_COLORMODEL 0x00000001L /* Match color model */ -#define D3DFDS_GUID 0x00000002L /* Match guid */ -#define D3DFDS_HARDWARE 0x00000004L /* Match hardware/software */ -#define D3DFDS_TRIANGLES 0x00000008L /* Match in triCaps */ -#define D3DFDS_LINES 0x00000010L /* Match in lineCaps */ -#define D3DFDS_MISCCAPS 0x00000020L /* Match primCaps.dwMiscCaps */ -#define D3DFDS_RASTERCAPS 0x00000040L /* Match primCaps.dwRasterCaps */ -#define D3DFDS_ZCMPCAPS 0x00000080L /* Match primCaps.dwZCmpCaps */ -#define D3DFDS_ALPHACMPCAPS 0x00000100L /* Match primCaps.dwAlphaCmpCaps */ -#define D3DFDS_SRCBLENDCAPS 0x00000200L /* Match primCaps.dwSourceBlendCaps */ -#define D3DFDS_DSTBLENDCAPS 0x00000400L /* Match primCaps.dwDestBlendCaps */ -#define D3DFDS_SHADECAPS 0x00000800L /* Match primCaps.dwShadeCaps */ -#define D3DFDS_TEXTURECAPS 0x00001000L /* Match primCaps.dwTextureCaps */ -#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */ -#define D3DFDS_TEXTUREBLENDCAPS 0x00004000L /* Match primCaps.dwTextureBlendCaps */ -#define D3DFDS_TEXTUREADDRESSCAPS 0x00008000L /* Match primCaps.dwTextureBlendCaps */ - -/* - * FindDevice arguments - */ -typedef struct _D3DFINDDEVICESEARCH { - DWORD dwSize; - DWORD dwFlags; - BOOL bHardware; - D3DCOLORMODEL dcmColorModel; - GUID guid; - DWORD dwCaps; - D3DPRIMCAPS dpcPrimCaps; -} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH; - -typedef struct _D3DFINDDEVICERESULT { - DWORD dwSize; - GUID guid; /* guid which matched */ - D3DDEVICEDESC ddHwDesc; /* hardware D3DDEVICEDESC */ - D3DDEVICEDESC ddSwDesc; /* software D3DDEVICEDESC */ -} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT; - -/* - * Description of execute buffer. - */ -typedef struct _D3DExecuteBufferDesc { - DWORD dwSize; /* size of this structure */ - DWORD dwFlags; /* flags indicating which fields are valid */ - DWORD dwCaps; /* capabilities of execute buffer */ - DWORD dwBufferSize; /* size of execute buffer data */ - LPVOID lpData; /* pointer to actual data */ -} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC; - -/* D3DEXECUTEBUFFER dwFlags indicating valid fields */ - -#define D3DDEB_BUFSIZE 0x00000001l /* buffer size valid */ -#define D3DDEB_CAPS 0x00000002l /* caps valid */ -#define D3DDEB_LPDATA 0x00000004l /* lpData valid */ - -/* D3DEXECUTEBUFFER dwCaps */ - -#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l /* buffer in system memory */ -#define D3DDEBCAPS_VIDEOMEMORY 0x00000002l /* buffer in device memory */ -#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY) - -#pragma pack() - -#endif /* _D3DCAPS_H_ */ +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3dcaps.h + * Content: Direct3D capabilities include file + * + ***************************************************************************/ + +#ifndef _D3DCAPS_H +#define _D3DCAPS_H + +/* + * Pull in DirectDraw include file automatically: + */ +#include + +#pragma pack(4) + +/* Description of capabilities of transform */ + +typedef struct _D3DTRANSFORMCAPS { + DWORD dwSize; + DWORD dwCaps; +} D3DTRANSFORMCAPS, *LPD3DTRANSFORMCAPS; + +#define D3DTRANSFORMCAPS_CLIP 0x00000001L /* Will clip whilst transforming */ + +/* Description of capabilities of lighting */ + +typedef struct _D3DLIGHTINGCAPS { + DWORD dwSize; + DWORD dwCaps; /* Lighting caps */ + DWORD dwLightingModel; /* Lighting model - RGB or mono */ + DWORD dwNumLights; /* Number of lights that can be handled */ +} D3DLIGHTINGCAPS, *LPD3DLIGHTINGCAPS; + +#define D3DLIGHTINGMODEL_RGB 0x00000001L +#define D3DLIGHTINGMODEL_MONO 0x00000002L + +#define D3DLIGHTCAPS_POINT 0x00000001L /* Point lights supported */ +#define D3DLIGHTCAPS_SPOT 0x00000002L /* Spot lights supported */ +#define D3DLIGHTCAPS_DIRECTIONAL 0x00000004L /* Directional lights supported */ +#define D3DLIGHTCAPS_PARALLELPOINT 0x00000008L /* Parallel point lights supported */ +#define D3DLIGHTCAPS_GLSPOT 0x00000010L /* GL syle spot lights supported */ + +/* Description of capabilities for each primitive type */ + +typedef struct _D3DPrimCaps { + DWORD dwSize; + DWORD dwMiscCaps; /* Capability flags */ + DWORD dwRasterCaps; + DWORD dwZCmpCaps; + DWORD dwSrcBlendCaps; + DWORD dwDestBlendCaps; + DWORD dwAlphaCmpCaps; + DWORD dwShadeCaps; + DWORD dwTextureCaps; + DWORD dwTextureFilterCaps; + DWORD dwTextureBlendCaps; + DWORD dwTextureAddressCaps; + DWORD dwStippleWidth; /* maximum width and height of */ + DWORD dwStippleHeight; /* of supported stipple (up to 32x32) */ +} D3DPRIMCAPS, *LPD3DPRIMCAPS; + +/* D3DPRIMCAPS dwMiscCaps */ + +#define D3DPMISCCAPS_MASKPLANES 0x00000001L +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L +#define D3DPMISCCAPS_CONFORMANT 0x00000008L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L + +/* D3DPRIMCAPS dwRasterCaps */ + +#define D3DPRASTERCAPS_DITHER 0x00000001L +#define D3DPRASTERCAPS_ROP2 0x00000002L +#define D3DPRASTERCAPS_XOR 0x00000004L +#define D3DPRASTERCAPS_PAT 0x00000008L +#define D3DPRASTERCAPS_ZTEST 0x00000010L +#define D3DPRASTERCAPS_SUBPIXEL 0x00000020L +#define D3DPRASTERCAPS_SUBPIXELX 0x00000040L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_STIPPLE 0x00000200L + +/* D3DPRIMCAPS dwZCmpCaps, dwAlphaCmpCaps */ + +#define D3DPCMPCAPS_NEVER 0x00000001L +#define D3DPCMPCAPS_LESS 0x00000002L +#define D3DPCMPCAPS_EQUAL 0x00000004L +#define D3DPCMPCAPS_LESSEQUAL 0x00000008L +#define D3DPCMPCAPS_GREATER 0x00000010L +#define D3DPCMPCAPS_NOTEQUAL 0x00000020L +#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L +#define D3DPCMPCAPS_ALWAYS 0x00000080L + +/* D3DPRIMCAPS dwSourceBlendCaps, dwDestBlendCaps */ + +#define D3DPBLENDCAPS_ZERO 0x00000001L +#define D3DPBLENDCAPS_ONE 0x00000002L +#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L +#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L +#define D3DPBLENDCAPS_SRCALPHA 0x00000010L +#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L +#define D3DPBLENDCAPS_DESTALPHA 0x00000040L +#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L +#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L +#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L +#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L +#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L +#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L + +/* D3DPRIMCAPS dwShadeCaps */ + +#define D3DPSHADECAPS_COLORFLATMONO 0x00000001L +#define D3DPSHADECAPS_COLORFLATRGB 0x00000002L +#define D3DPSHADECAPS_COLORGOURAUDMONO 0x00000004L +#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L +#define D3DPSHADECAPS_COLORPHONGMONO 0x00000010L +#define D3DPSHADECAPS_COLORPHONGRGB 0x00000020L + +#define D3DPSHADECAPS_SPECULARFLATMONO 0x00000040L +#define D3DPSHADECAPS_SPECULARFLATRGB 0x00000080L +#define D3DPSHADECAPS_SPECULARGOURAUDMONO 0x00000100L +#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L +#define D3DPSHADECAPS_SPECULARPHONGMONO 0x00000400L +#define D3DPSHADECAPS_SPECULARPHONGRGB 0x00000800L + +#define D3DPSHADECAPS_ALPHAFLATBLEND 0x00001000L +#define D3DPSHADECAPS_ALPHAFLATSTIPPLED 0x00002000L +#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L +#define D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED 0x00008000L +#define D3DPSHADECAPS_ALPHAPHONGBLEND 0x00010000L +#define D3DPSHADECAPS_ALPHAPHONGSTIPPLED 0x00020000L + +#define D3DPSHADECAPS_FOGFLAT 0x00040000L +#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L +#define D3DPSHADECAPS_FOGPHONG 0x00100000L + +/* D3DPRIMCAPS dwTextureCaps */ + +#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L +#define D3DPTEXTURECAPS_POW2 0x00000002L +#define D3DPTEXTURECAPS_ALPHA 0x00000004L +#define D3DPTEXTURECAPS_TRANSPARENCY 0x00000008L +#define D3DPTEXTURECAPS_BORDER 0x00000010L +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L + +/* D3DPRIMCAPS dwTextureFilterCaps */ + +#define D3DPTFILTERCAPS_NEAREST 0x00000001L +#define D3DPTFILTERCAPS_LINEAR 0x00000002L +#define D3DPTFILTERCAPS_MIPNEAREST 0x00000004L +#define D3DPTFILTERCAPS_MIPLINEAR 0x00000008L +#define D3DPTFILTERCAPS_LINEARMIPNEAREST 0x00000010L +#define D3DPTFILTERCAPS_LINEARMIPLINEAR 0x00000020L + +/* D3DPRIMCAPS dwTextureBlendCaps */ + +#define D3DPTBLENDCAPS_DECAL 0x00000001L +#define D3DPTBLENDCAPS_MODULATE 0x00000002L +#define D3DPTBLENDCAPS_DECALALPHA 0x00000004L +#define D3DPTBLENDCAPS_MODULATEALPHA 0x00000008L +#define D3DPTBLENDCAPS_DECALMASK 0x00000010L +#define D3DPTBLENDCAPS_MODULATEMASK 0x00000020L +#define D3DPTBLENDCAPS_COPY 0x00000040L + +/* D3DPRIMCAPS dwTextureAddressCaps */ +#define D3DPTADDRESSCAPS_WRAP 0x00000001L +#define D3DPTADDRESSCAPS_MIRROR 0x00000002L +#define D3DPTADDRESSCAPS_CLAMP 0x00000004L + +/* + * Description for a device. + * This is used to describe a device that is to be created or to query + * the current device. + */ +typedef struct _D3DDeviceDesc { + DWORD dwSize; /* Size of D3DDEVICEDESC structure */ + DWORD dwFlags; /* Indicates which fields have valid data */ + D3DCOLORMODEL dcmColorModel; /* Color model of device */ + DWORD dwDevCaps; /* Capabilities of device */ + D3DTRANSFORMCAPS dtcTransformCaps; /* Capabilities of transform */ + BOOL bClipping; /* Device can do 3D clipping */ + D3DLIGHTINGCAPS dlcLightingCaps; /* Capabilities of lighting */ + D3DPRIMCAPS dpcLineCaps; + D3DPRIMCAPS dpcTriCaps; + DWORD dwDeviceRenderBitDepth; /* One of DDBB_8, 16, etc.. */ + DWORD dwDeviceZBufferBitDepth;/* One of DDBD_16, 32, etc.. */ + DWORD dwMaxBufferSize; /* Maximum execute buffer size */ + DWORD dwMaxVertexCount; /* Maximum vertex count */ +} D3DDEVICEDESC, *LPD3DDEVICEDESC; + +typedef HRESULT (FAR PASCAL * LPD3DENUMDEVICESCALLBACK)(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC, LPD3DDEVICEDESC, LPVOID); + +/* D3DDEVICEDESC dwFlags indicating valid fields */ + +#define D3DDD_COLORMODEL 0x00000001L /* dcmColorModel is valid */ +#define D3DDD_DEVCAPS 0x00000002L /* dwDevCaps is valid */ +#define D3DDD_TRANSFORMCAPS 0x00000004L /* dtcTransformCaps is valid */ +#define D3DDD_LIGHTINGCAPS 0x00000008L /* dlcLightingCaps is valid */ +#define D3DDD_BCLIPPING 0x00000010L /* bClipping is valid */ +#define D3DDD_LINECAPS 0x00000020L /* dpcLineCaps is valid */ +#define D3DDD_TRICAPS 0x00000040L /* dpcTriCaps is valid */ +#define D3DDD_DEVICERENDERBITDEPTH 0x00000080L /* dwDeviceRenderBitDepth is valid */ +#define D3DDD_DEVICEZBUFFERBITDEPTH 0x00000100L /* dwDeviceZBufferBitDepth is valid */ +#define D3DDD_MAXBUFFERSIZE 0x00000200L /* dwMaxBufferSize is valid */ +#define D3DDD_MAXVERTEXCOUNT 0x00000400L /* dwMaxVertexCount is valid */ + +/* D3DDEVICEDESC dwDevCaps flags */ + +#define D3DDEVCAPS_FLOATTLVERTEX 0x00000001L /* Device accepts floating point */ + /* for post-transform vertex data */ +#define D3DDEVCAPS_SORTINCREASINGZ 0x00000002L /* Device needs data sorted for increasing Z*/ +#define D3DDEVCAPS_SORTDECREASINGZ 0X00000004L /* Device needs data sorted for decreasing Z*/ +#define D3DDEVCAPS_SORTEXACT 0x00000008L /* Device needs data sorted exactly */ + +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ + +#define D3DFDS_COLORMODEL 0x00000001L /* Match color model */ +#define D3DFDS_GUID 0x00000002L /* Match guid */ +#define D3DFDS_HARDWARE 0x00000004L /* Match hardware/software */ +#define D3DFDS_TRIANGLES 0x00000008L /* Match in triCaps */ +#define D3DFDS_LINES 0x00000010L /* Match in lineCaps */ +#define D3DFDS_MISCCAPS 0x00000020L /* Match primCaps.dwMiscCaps */ +#define D3DFDS_RASTERCAPS 0x00000040L /* Match primCaps.dwRasterCaps */ +#define D3DFDS_ZCMPCAPS 0x00000080L /* Match primCaps.dwZCmpCaps */ +#define D3DFDS_ALPHACMPCAPS 0x00000100L /* Match primCaps.dwAlphaCmpCaps */ +#define D3DFDS_SRCBLENDCAPS 0x00000200L /* Match primCaps.dwSourceBlendCaps */ +#define D3DFDS_DSTBLENDCAPS 0x00000400L /* Match primCaps.dwDestBlendCaps */ +#define D3DFDS_SHADECAPS 0x00000800L /* Match primCaps.dwShadeCaps */ +#define D3DFDS_TEXTURECAPS 0x00001000L /* Match primCaps.dwTextureCaps */ +#define D3DFDS_TEXTUREFILTERCAPS 0x00002000L /* Match primCaps.dwTextureFilterCaps */ +#define D3DFDS_TEXTUREBLENDCAPS 0x00004000L /* Match primCaps.dwTextureBlendCaps */ +#define D3DFDS_TEXTUREADDRESSCAPS 0x00008000L /* Match primCaps.dwTextureBlendCaps */ + +/* + * FindDevice arguments + */ +typedef struct _D3DFINDDEVICESEARCH { + DWORD dwSize; + DWORD dwFlags; + BOOL bHardware; + D3DCOLORMODEL dcmColorModel; + GUID guid; + DWORD dwCaps; + D3DPRIMCAPS dpcPrimCaps; +} D3DFINDDEVICESEARCH, *LPD3DFINDDEVICESEARCH; + +typedef struct _D3DFINDDEVICERESULT { + DWORD dwSize; + GUID guid; /* guid which matched */ + D3DDEVICEDESC ddHwDesc; /* hardware D3DDEVICEDESC */ + D3DDEVICEDESC ddSwDesc; /* software D3DDEVICEDESC */ +} D3DFINDDEVICERESULT, *LPD3DFINDDEVICERESULT; + +/* + * Description of execute buffer. + */ +typedef struct _D3DExecuteBufferDesc { + DWORD dwSize; /* size of this structure */ + DWORD dwFlags; /* flags indicating which fields are valid */ + DWORD dwCaps; /* capabilities of execute buffer */ + DWORD dwBufferSize; /* size of execute buffer data */ + LPVOID lpData; /* pointer to actual data */ +} D3DEXECUTEBUFFERDESC, *LPD3DEXECUTEBUFFERDESC; + +/* D3DEXECUTEBUFFER dwFlags indicating valid fields */ + +#define D3DDEB_BUFSIZE 0x00000001l /* buffer size valid */ +#define D3DDEB_CAPS 0x00000002l /* caps valid */ +#define D3DDEB_LPDATA 0x00000004l /* lpData valid */ + +/* D3DEXECUTEBUFFER dwCaps */ + +#define D3DDEBCAPS_SYSTEMMEMORY 0x00000001l /* buffer in system memory */ +#define D3DDEBCAPS_VIDEOMEMORY 0x00000002l /* buffer in device memory */ +#define D3DDEBCAPS_MEM (D3DDEBCAPS_SYSTEMMEMORY|D3DDEBCAPS_VIDEOMEMORY) + +#pragma pack() + +#endif /* _D3DCAPS_H_ */ diff --git a/WinQuake/dxsdk/SDK/INC/D3DRM.H b/WinQuake/dxsdk/SDK/INC/D3DRM.H index 52f5e4a..d40ec1c 100644 --- a/WinQuake/dxsdk/SDK/INC/D3DRM.H +++ b/WinQuake/dxsdk/SDK/INC/D3DRM.H @@ -1,134 +1,134 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3drm.h - * Content: Direct3DRM include file - * - ***************************************************************************/ - -#ifndef __D3DRM_H__ -#define __D3DRM_H__ - -#include "d3drmobj.h" - -#ifdef __cplusplus -extern "C" { -struct IDirect3DRM; -#endif - - -typedef void (*D3DRMDEVICEPALETTECALLBACK) - (LPDIRECT3DRMDEVICE lpDirect3DRMDev, LPVOID lpArg, DWORD dwIndex, LONG red, LONG green, LONG blue); - -DEFINE_GUID(IID_IDirect3DRM, 0x2bc49361, 0x8327, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -WIN_TYPES(IDirect3DRM, DIRECT3DRM); - - -/* Create a Direct3DRM API */ -STDAPI Direct3DRMCreate(LPDIRECT3DRM FAR *lplpDirect3DRM); - -#undef INTERFACE -#define INTERFACE IDirect3DRM - -DECLARE_INTERFACE_(IDirect3DRM, IUnknown) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD(CreateObject) - (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE; - STDMETHOD(CreateFrame) (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME *) PURE; - STDMETHOD(CreateMesh) (THIS_ LPDIRECT3DRMMESH *) PURE; - STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER *) PURE; - STDMETHOD(CreateFace) (THIS_ LPDIRECT3DRMFACE *) PURE; - STDMETHOD(CreateAnimation) (THIS_ LPDIRECT3DRMANIMATION *) PURE; - STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE; - STDMETHOD(CreateTexture) (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE *) PURE; - STDMETHOD(CreateLight) (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE; - STDMETHOD(CreateLightRGB) - (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE; - STDMETHOD(CreateMaterial) (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE; - STDMETHOD(CreateDevice) (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE *) PURE; - - /* Create a Windows Device using DirectDraw surfaces */ - STDMETHOD(CreateDeviceFromSurface) - ( THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD, - LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE * - ) PURE; - - /* Create a Windows Device using D3D objects */ - STDMETHOD(CreateDeviceFromD3D) - ( THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev, - LPDIRECT3DRMDEVICE * - ) PURE; - - STDMETHOD(CreateDeviceFromClipper) - ( THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, - int width, int height, LPDIRECT3DRMDEVICE *) PURE; - - STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE *) PURE; - - STDMETHOD(CreateShadow) - ( THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT, - D3DVALUE px, D3DVALUE py, D3DVALUE pz, - D3DVALUE nx, D3DVALUE ny, D3DVALUE nz, - LPDIRECT3DRMVISUAL * - ) PURE; - STDMETHOD(CreateViewport) - ( THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD, - DWORD, DWORD, LPDIRECT3DRMVIEWPORT * - ) PURE; - STDMETHOD(CreateWrap) - ( THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME, - D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, - D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, - D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, - D3DVALUE ou, D3DVALUE ov, - D3DVALUE su, D3DVALUE sv, - LPDIRECT3DRMWRAP * - ) PURE; - STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE; - STDMETHOD(LoadTexture) (THIS_ const char *, LPDIRECT3DRMTEXTURE *) PURE; - STDMETHOD(LoadTextureFromResource) (THIS_ HRSRC rs, LPDIRECT3DRMTEXTURE *) PURE; - - STDMETHOD(SetSearchPath) (THIS_ LPCSTR) PURE; - STDMETHOD(AddSearchPath) (THIS_ LPCSTR) PURE; - STDMETHOD(GetSearchPath) (THIS_ DWORD *size_return, LPSTR path_return); - //STDMETHOD(GetSearchPath) (THIS_ int *return_count, char ***return_path) PURE; - STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE; - STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE; - - STDMETHOD(GetDevices) (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE; - STDMETHOD(GetNamedObject) (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE; - - STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE; - - STDMETHOD(Load) - ( THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS, - D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID, - LPDIRECT3DRMFRAME - ) PURE; - STDMETHOD(Tick) (THIS_ D3DVALUE) PURE; -}; - -#define D3DRM_OK DD_OK -#define D3DRMERR_BADOBJECT MAKE_DDHRESULT(781) -#define D3DRMERR_BADTYPE MAKE_DDHRESULT(782) -#define D3DRMERR_BADALLOC MAKE_DDHRESULT(783) -#define D3DRMERR_FACEUSED MAKE_DDHRESULT(784) -#define D3DRMERR_NOTFOUND MAKE_DDHRESULT(785) -#define D3DRMERR_NOTDONEYET MAKE_DDHRESULT(786) -#define D3DRMERR_FILENOTFOUND MAKE_DDHRESULT(787) -#define D3DRMERR_BADFILE MAKE_DDHRESULT(788) -#define D3DRMERR_BADDEVICE MAKE_DDHRESULT(789) -#define D3DRMERR_BADVALUE MAKE_DDHRESULT(790) -#define D3DRMERR_BADMAJORVERSION MAKE_DDHRESULT(791) -#define D3DRMERR_BADMINORVERSION MAKE_DDHRESULT(792) -#define D3DRMERR_UNABLETOEXECUTE MAKE_DDHRESULT(793) - -#ifdef __cplusplus -}; -#endif - -#endif /* _D3DRMAPI_H_ */ - +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3drm.h + * Content: Direct3DRM include file + * + ***************************************************************************/ + +#ifndef __D3DRM_H__ +#define __D3DRM_H__ + +#include "d3drmobj.h" + +#ifdef __cplusplus +extern "C" { +struct IDirect3DRM; +#endif + + +typedef void (*D3DRMDEVICEPALETTECALLBACK) + (LPDIRECT3DRMDEVICE lpDirect3DRMDev, LPVOID lpArg, DWORD dwIndex, LONG red, LONG green, LONG blue); + +DEFINE_GUID(IID_IDirect3DRM, 0x2bc49361, 0x8327, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +WIN_TYPES(IDirect3DRM, DIRECT3DRM); + + +/* Create a Direct3DRM API */ +STDAPI Direct3DRMCreate(LPDIRECT3DRM FAR *lplpDirect3DRM); + +#undef INTERFACE +#define INTERFACE IDirect3DRM + +DECLARE_INTERFACE_(IDirect3DRM, IUnknown) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD(CreateObject) + (THIS_ REFCLSID rclsid, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR* ppv) PURE; + STDMETHOD(CreateFrame) (THIS_ LPDIRECT3DRMFRAME, LPDIRECT3DRMFRAME *) PURE; + STDMETHOD(CreateMesh) (THIS_ LPDIRECT3DRMMESH *) PURE; + STDMETHOD(CreateMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER *) PURE; + STDMETHOD(CreateFace) (THIS_ LPDIRECT3DRMFACE *) PURE; + STDMETHOD(CreateAnimation) (THIS_ LPDIRECT3DRMANIMATION *) PURE; + STDMETHOD(CreateAnimationSet)(THIS_ LPDIRECT3DRMANIMATIONSET *) PURE; + STDMETHOD(CreateTexture) (THIS_ LPD3DRMIMAGE, LPDIRECT3DRMTEXTURE *) PURE; + STDMETHOD(CreateLight) (THIS_ D3DRMLIGHTTYPE, D3DCOLOR, LPDIRECT3DRMLIGHT *) PURE; + STDMETHOD(CreateLightRGB) + (THIS_ D3DRMLIGHTTYPE, D3DVALUE, D3DVALUE, D3DVALUE, LPDIRECT3DRMLIGHT *) PURE; + STDMETHOD(CreateMaterial) (THIS_ D3DVALUE, LPDIRECT3DRMMATERIAL *) PURE; + STDMETHOD(CreateDevice) (THIS_ DWORD, DWORD, LPDIRECT3DRMDEVICE *) PURE; + + /* Create a Windows Device using DirectDraw surfaces */ + STDMETHOD(CreateDeviceFromSurface) + ( THIS_ LPGUID lpGUID, LPDIRECTDRAW lpDD, + LPDIRECTDRAWSURFACE lpDDSBack, LPDIRECT3DRMDEVICE * + ) PURE; + + /* Create a Windows Device using D3D objects */ + STDMETHOD(CreateDeviceFromD3D) + ( THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev, + LPDIRECT3DRMDEVICE * + ) PURE; + + STDMETHOD(CreateDeviceFromClipper) + ( THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, + int width, int height, LPDIRECT3DRMDEVICE *) PURE; + + STDMETHOD(CreateTextureFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS, LPDIRECT3DRMTEXTURE *) PURE; + + STDMETHOD(CreateShadow) + ( THIS_ LPDIRECT3DRMVISUAL, LPDIRECT3DRMLIGHT, + D3DVALUE px, D3DVALUE py, D3DVALUE pz, + D3DVALUE nx, D3DVALUE ny, D3DVALUE nz, + LPDIRECT3DRMVISUAL * + ) PURE; + STDMETHOD(CreateViewport) + ( THIS_ LPDIRECT3DRMDEVICE, LPDIRECT3DRMFRAME, DWORD, DWORD, + DWORD, DWORD, LPDIRECT3DRMVIEWPORT * + ) PURE; + STDMETHOD(CreateWrap) + ( THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME, + D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, + D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, + D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, + D3DVALUE ou, D3DVALUE ov, + D3DVALUE su, D3DVALUE sv, + LPDIRECT3DRMWRAP * + ) PURE; + STDMETHOD(CreateUserVisual) (THIS_ D3DRMUSERVISUALCALLBACK, LPVOID lPArg, LPDIRECT3DRMUSERVISUAL *) PURE; + STDMETHOD(LoadTexture) (THIS_ const char *, LPDIRECT3DRMTEXTURE *) PURE; + STDMETHOD(LoadTextureFromResource) (THIS_ HRSRC rs, LPDIRECT3DRMTEXTURE *) PURE; + + STDMETHOD(SetSearchPath) (THIS_ LPCSTR) PURE; + STDMETHOD(AddSearchPath) (THIS_ LPCSTR) PURE; + STDMETHOD(GetSearchPath) (THIS_ DWORD *size_return, LPSTR path_return); + //STDMETHOD(GetSearchPath) (THIS_ int *return_count, char ***return_path) PURE; + STDMETHOD(SetDefaultTextureColors)(THIS_ DWORD) PURE; + STDMETHOD(SetDefaultTextureShades)(THIS_ DWORD) PURE; + + STDMETHOD(GetDevices) (THIS_ LPDIRECT3DRMDEVICEARRAY *) PURE; + STDMETHOD(GetNamedObject) (THIS_ const char *, LPDIRECT3DRMOBJECT *) PURE; + + STDMETHOD(EnumerateObjects) (THIS_ D3DRMOBJECTCALLBACK, LPVOID) PURE; + + STDMETHOD(Load) + ( THIS_ LPVOID, LPVOID, LPIID *, DWORD, D3DRMLOADOPTIONS, + D3DRMLOADCALLBACK, LPVOID, D3DRMLOADTEXTURECALLBACK, LPVOID, + LPDIRECT3DRMFRAME + ) PURE; + STDMETHOD(Tick) (THIS_ D3DVALUE) PURE; +}; + +#define D3DRM_OK DD_OK +#define D3DRMERR_BADOBJECT MAKE_DDHRESULT(781) +#define D3DRMERR_BADTYPE MAKE_DDHRESULT(782) +#define D3DRMERR_BADALLOC MAKE_DDHRESULT(783) +#define D3DRMERR_FACEUSED MAKE_DDHRESULT(784) +#define D3DRMERR_NOTFOUND MAKE_DDHRESULT(785) +#define D3DRMERR_NOTDONEYET MAKE_DDHRESULT(786) +#define D3DRMERR_FILENOTFOUND MAKE_DDHRESULT(787) +#define D3DRMERR_BADFILE MAKE_DDHRESULT(788) +#define D3DRMERR_BADDEVICE MAKE_DDHRESULT(789) +#define D3DRMERR_BADVALUE MAKE_DDHRESULT(790) +#define D3DRMERR_BADMAJORVERSION MAKE_DDHRESULT(791) +#define D3DRMERR_BADMINORVERSION MAKE_DDHRESULT(792) +#define D3DRMERR_UNABLETOEXECUTE MAKE_DDHRESULT(793) + +#ifdef __cplusplus +}; +#endif + +#endif /* _D3DRMAPI_H_ */ + diff --git a/WinQuake/dxsdk/SDK/INC/D3DRMDEF.H b/WinQuake/dxsdk/SDK/INC/D3DRMDEF.H index f52bad5..66cdf74 100644 --- a/WinQuake/dxsdk/SDK/INC/D3DRMDEF.H +++ b/WinQuake/dxsdk/SDK/INC/D3DRMDEF.H @@ -1,402 +1,402 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3drm.h - * Content: Direct3DRM include file - * - ***************************************************************************/ - -#ifndef __D3DRMDEFS_H__ -#define __D3DRMDEFS_H__ - -#include -#include "d3dtypes.h" - -#ifdef WIN32 -#define D3DRMAPI __stdcall -#else -#define D3DRMAPI -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef TRUE -#define FALSE 0 -#define TRUE 1 -#endif - -typedef struct _D3DRMVECTOR4D -{ D3DVALUE x, y, z, w; -} D3DRMVECTOR4D, *LPD3DRMVECTOR4D; - -typedef D3DVALUE D3DRMMATRIX4D[4][4]; - -typedef struct _D3DRMQUATERNION -{ D3DVALUE s; - D3DVECTOR v; -} D3DRMQUATERNION, *LPD3DRMQUATERNION; - -typedef struct _D3DRMBOX -{ D3DVECTOR min, max; -} D3DRMBOX, *LPD3DRMBOX; - -typedef void (*D3DRMWRAPCALLBACK) - (LPD3DVECTOR, int* u, int* v, LPD3DVECTOR a, LPD3DVECTOR b, LPVOID); - -typedef enum _D3DRMLIGHTTYPE -{ D3DRMLIGHT_AMBIENT, - D3DRMLIGHT_POINT, - D3DRMLIGHT_SPOT, - D3DRMLIGHT_DIRECTIONAL, - D3DRMLIGHT_PARALLELPOINT -} D3DRMLIGHTTYPE, *LPD3DRMLIGHTTYPE; - -typedef enum _D3DRMSHADEMODE { - D3DRMSHADE_FLAT = 0, - D3DRMSHADE_GOURAUD = 1, - D3DRMSHADE_PHONG = 2, - - D3DRMSHADE_MASK = 7, - D3DRMSHADE_MAX = 8 -} D3DRMSHADEMODE, *LPD3DRMSHADEMODE; - -typedef enum _D3DRMLIGHTMODE { - D3DRMLIGHT_OFF = 0 * D3DRMSHADE_MAX, - D3DRMLIGHT_ON = 1 * D3DRMSHADE_MAX, - - D3DRMLIGHT_MASK = 7 * D3DRMSHADE_MAX, - D3DRMLIGHT_MAX = 8 * D3DRMSHADE_MAX -} D3DRMLIGHTMODE, *LPD3DRMLIGHTMODE; - -typedef enum _D3DRMFILLMODE { - D3DRMFILL_POINTS = 0 * D3DRMLIGHT_MAX, - D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX, - D3DRMFILL_SOLID = 2 * D3DRMLIGHT_MAX, - - D3DRMFILL_MASK = 7 * D3DRMLIGHT_MAX, - D3DRMFILL_MAX = 8 * D3DRMLIGHT_MAX -} D3DRMFILLMODE, *LPD3DRMFILLMODE; - -typedef DWORD D3DRMRENDERQUALITY, *LPD3DRMRENDERQUALITY; - -#define D3DRMRENDER_WIREFRAME (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME) -#define D3DRMRENDER_UNLITFLAT (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID) -#define D3DRMRENDER_FLAT (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID) -#define D3DRMRENDER_GOURAUD (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID) -#define D3DRMRENDER_PHONG (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID) - -typedef enum _D3DRMTEXTUREQUALITY -{ D3DRMTEXTURE_NEAREST, /* choose nearest texel */ - D3DRMTEXTURE_LINEAR, /* interpolate 4 texels */ - D3DRMTEXTURE_MIPNEAREST, /* nearest texel in nearest mipmap */ - D3DRMTEXTURE_MIPLINEAR, /* interpolate 2 texels from 2 mipmaps */ - D3DRMTEXTURE_LINEARMIPNEAREST, /* interpolate 4 texels in nearest mipmap */ - D3DRMTEXTURE_LINEARMIPLINEAR /* interpolate 8 texels from 2 mipmaps */ -} D3DRMTEXTUREQUALITY, *LPD3DRMTEXTUREQUALITY; - -typedef enum _D3DRMCOMBINETYPE -{ D3DRMCOMBINE_REPLACE, - D3DRMCOMBINE_BEFORE, - D3DRMCOMBINE_AFTER -} D3DRMCOMBINETYPE, *LPD3DRMCOMBINETYPE; - -typedef D3DCOLORMODEL D3DRMCOLORMODEL, *LPD3DRMCOLORMODEL; - -typedef enum _D3DRMPALETTEFLAGS -{ D3DRMPALETTE_FREE, /* renderer may use this entry freely */ - D3DRMPALETTE_READONLY, /* fixed but may be used by renderer */ - D3DRMPALETTE_RESERVED /* may not be used by renderer */ -} D3DRMPALETTEFLAGS, *LPD3DRMPALETTEFLAGS; - -typedef struct _D3DRMPALETTEENTRY -{ unsigned char red; /* 0 .. 255 */ - unsigned char green; /* 0 .. 255 */ - unsigned char blue; /* 0 .. 255 */ - unsigned char flags; /* one of D3DRMPALETTEFLAGS */ -} D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY; - -typedef struct _D3DRMIMAGE -{ int width, height; /* width and height in pixels */ - int aspectx, aspecty; /* aspect ratio for non-square pixels */ - int depth; /* bits per pixel */ - int rgb; /* if false, pixels are indices into a - palette otherwise, pixels encode - RGB values. */ - int bytes_per_line; /* number of bytes of memory for a - scanline. This must be a multiple - of 4. */ - void* buffer1; /* memory to render into (first buffer). */ - void* buffer2; /* second rendering buffer for double - buffering, set to NULL for single - buffering. */ - unsigned long red_mask; - unsigned long green_mask; - unsigned long blue_mask; - unsigned long alpha_mask; /* if rgb is true, these are masks for - the red, green and blue parts of a - pixel. Otherwise, these are masks - for the significant bits of the - red, green and blue elements in the - palette. For instance, most SVGA - displays use 64 intensities of red, - green and blue, so the masks should - all be set to 0xfc. */ - int palette_size; /* number of entries in palette */ - D3DRMPALETTEENTRY* palette; /* description of the palette (only if - rgb is false). Must be (1< +#include "d3dtypes.h" + +#ifdef WIN32 +#define D3DRMAPI __stdcall +#else +#define D3DRMAPI +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +typedef struct _D3DRMVECTOR4D +{ D3DVALUE x, y, z, w; +} D3DRMVECTOR4D, *LPD3DRMVECTOR4D; + +typedef D3DVALUE D3DRMMATRIX4D[4][4]; + +typedef struct _D3DRMQUATERNION +{ D3DVALUE s; + D3DVECTOR v; +} D3DRMQUATERNION, *LPD3DRMQUATERNION; + +typedef struct _D3DRMBOX +{ D3DVECTOR min, max; +} D3DRMBOX, *LPD3DRMBOX; + +typedef void (*D3DRMWRAPCALLBACK) + (LPD3DVECTOR, int* u, int* v, LPD3DVECTOR a, LPD3DVECTOR b, LPVOID); + +typedef enum _D3DRMLIGHTTYPE +{ D3DRMLIGHT_AMBIENT, + D3DRMLIGHT_POINT, + D3DRMLIGHT_SPOT, + D3DRMLIGHT_DIRECTIONAL, + D3DRMLIGHT_PARALLELPOINT +} D3DRMLIGHTTYPE, *LPD3DRMLIGHTTYPE; + +typedef enum _D3DRMSHADEMODE { + D3DRMSHADE_FLAT = 0, + D3DRMSHADE_GOURAUD = 1, + D3DRMSHADE_PHONG = 2, + + D3DRMSHADE_MASK = 7, + D3DRMSHADE_MAX = 8 +} D3DRMSHADEMODE, *LPD3DRMSHADEMODE; + +typedef enum _D3DRMLIGHTMODE { + D3DRMLIGHT_OFF = 0 * D3DRMSHADE_MAX, + D3DRMLIGHT_ON = 1 * D3DRMSHADE_MAX, + + D3DRMLIGHT_MASK = 7 * D3DRMSHADE_MAX, + D3DRMLIGHT_MAX = 8 * D3DRMSHADE_MAX +} D3DRMLIGHTMODE, *LPD3DRMLIGHTMODE; + +typedef enum _D3DRMFILLMODE { + D3DRMFILL_POINTS = 0 * D3DRMLIGHT_MAX, + D3DRMFILL_WIREFRAME = 1 * D3DRMLIGHT_MAX, + D3DRMFILL_SOLID = 2 * D3DRMLIGHT_MAX, + + D3DRMFILL_MASK = 7 * D3DRMLIGHT_MAX, + D3DRMFILL_MAX = 8 * D3DRMLIGHT_MAX +} D3DRMFILLMODE, *LPD3DRMFILLMODE; + +typedef DWORD D3DRMRENDERQUALITY, *LPD3DRMRENDERQUALITY; + +#define D3DRMRENDER_WIREFRAME (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_WIREFRAME) +#define D3DRMRENDER_UNLITFLAT (D3DRMSHADE_FLAT+D3DRMLIGHT_OFF+D3DRMFILL_SOLID) +#define D3DRMRENDER_FLAT (D3DRMSHADE_FLAT+D3DRMLIGHT_ON+D3DRMFILL_SOLID) +#define D3DRMRENDER_GOURAUD (D3DRMSHADE_GOURAUD+D3DRMLIGHT_ON+D3DRMFILL_SOLID) +#define D3DRMRENDER_PHONG (D3DRMSHADE_PHONG+D3DRMLIGHT_ON+D3DRMFILL_SOLID) + +typedef enum _D3DRMTEXTUREQUALITY +{ D3DRMTEXTURE_NEAREST, /* choose nearest texel */ + D3DRMTEXTURE_LINEAR, /* interpolate 4 texels */ + D3DRMTEXTURE_MIPNEAREST, /* nearest texel in nearest mipmap */ + D3DRMTEXTURE_MIPLINEAR, /* interpolate 2 texels from 2 mipmaps */ + D3DRMTEXTURE_LINEARMIPNEAREST, /* interpolate 4 texels in nearest mipmap */ + D3DRMTEXTURE_LINEARMIPLINEAR /* interpolate 8 texels from 2 mipmaps */ +} D3DRMTEXTUREQUALITY, *LPD3DRMTEXTUREQUALITY; + +typedef enum _D3DRMCOMBINETYPE +{ D3DRMCOMBINE_REPLACE, + D3DRMCOMBINE_BEFORE, + D3DRMCOMBINE_AFTER +} D3DRMCOMBINETYPE, *LPD3DRMCOMBINETYPE; + +typedef D3DCOLORMODEL D3DRMCOLORMODEL, *LPD3DRMCOLORMODEL; + +typedef enum _D3DRMPALETTEFLAGS +{ D3DRMPALETTE_FREE, /* renderer may use this entry freely */ + D3DRMPALETTE_READONLY, /* fixed but may be used by renderer */ + D3DRMPALETTE_RESERVED /* may not be used by renderer */ +} D3DRMPALETTEFLAGS, *LPD3DRMPALETTEFLAGS; + +typedef struct _D3DRMPALETTEENTRY +{ unsigned char red; /* 0 .. 255 */ + unsigned char green; /* 0 .. 255 */ + unsigned char blue; /* 0 .. 255 */ + unsigned char flags; /* one of D3DRMPALETTEFLAGS */ +} D3DRMPALETTEENTRY, *LPD3DRMPALETTEENTRY; + +typedef struct _D3DRMIMAGE +{ int width, height; /* width and height in pixels */ + int aspectx, aspecty; /* aspect ratio for non-square pixels */ + int depth; /* bits per pixel */ + int rgb; /* if false, pixels are indices into a + palette otherwise, pixels encode + RGB values. */ + int bytes_per_line; /* number of bytes of memory for a + scanline. This must be a multiple + of 4. */ + void* buffer1; /* memory to render into (first buffer). */ + void* buffer2; /* second rendering buffer for double + buffering, set to NULL for single + buffering. */ + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + unsigned long alpha_mask; /* if rgb is true, these are masks for + the red, green and blue parts of a + pixel. Otherwise, these are masks + for the significant bits of the + red, green and blue elements in the + palette. For instance, most SVGA + displays use 64 intensities of red, + green and blue, so the masks should + all be set to 0xfc. */ + int palette_size; /* number of entries in palette */ + D3DRMPALETTEENTRY* palette; /* description of the palette (only if + rgb is false). Must be (1< /* Use Windows header files */ -#define VIRTUAL - -#include "d3drmdef.h" -#include "d3d.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The methods for IUnknown - */ -#define IUNKNOWN_METHODS(kind) \ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) kind; \ - STDMETHOD_(ULONG, AddRef) (THIS) kind; \ - STDMETHOD_(ULONG, Release) (THIS) kind - -/* - * The methods for IDirect3DRMObject - */ -#define IDIRECT3DRMOBJECT_METHODS(kind) \ - STDMETHOD(Clone) (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) kind; \ - STDMETHOD(AddDestroyCallback) (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \ - STDMETHOD(DeleteDestroyCallback) (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \ - STDMETHOD(SetAppData) (THIS_ DWORD data) kind; \ - STDMETHOD_(DWORD, GetAppData) (THIS) kind; \ - STDMETHOD(SetName) (THIS_ LPCSTR) kind; \ - STDMETHOD(GetName) (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind; \ - STDMETHOD(GetClassName) (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind - - -#define WIN_TYPES(itype, ptype) \ - typedef interface itype FAR *LP##ptype, FAR **LPLP##ptype - -WIN_TYPES(IDirect3DRMObject, DIRECT3DRMOBJECT); -WIN_TYPES(IDirect3DRMDevice, DIRECT3DRMDEVICE); -WIN_TYPES(IDirect3DRMViewport, DIRECT3DRMVIEWPORT); -WIN_TYPES(IDirect3DRMFrame, DIRECT3DRMFRAME); -WIN_TYPES(IDirect3DRMVisual, DIRECT3DRMVISUAL); -WIN_TYPES(IDirect3DRMMesh, DIRECT3DRMMESH); -WIN_TYPES(IDirect3DRMMeshBuilder, DIRECT3DRMMESHBUILDER); -WIN_TYPES(IDirect3DRMFace, DIRECT3DRMFACE); -WIN_TYPES(IDirect3DRMLight, DIRECT3DRMLIGHT); -WIN_TYPES(IDirect3DRMTexture, DIRECT3DRMTEXTURE); -WIN_TYPES(IDirect3DRMWrap, DIRECT3DRMWRAP); -WIN_TYPES(IDirect3DRMMaterial, DIRECT3DRMMATERIAL); -WIN_TYPES(IDirect3DRMAnimation, DIRECT3DRMANIMATION); -WIN_TYPES(IDirect3DRMAnimationSet, DIRECT3DRMANIMATIONSET); -WIN_TYPES(IDirect3DRMUserVisual, DIRECT3DRMUSERVISUAL); -WIN_TYPES(IDirect3DRMShadow, DIRECT3DRMSHADOW); -WIN_TYPES(IDirect3DRMArray, DIRECT3DRMOBJECTARRAY); -WIN_TYPES(IDirect3DRMDeviceArray, DIRECT3DRMDEVICEARRAY); -WIN_TYPES(IDirect3DRMFaceArray, DIRECT3DRMFACEARRAY); -WIN_TYPES(IDirect3DRMViewportArray, DIRECT3DRMVIEWPORTARRAY); -WIN_TYPES(IDirect3DRMFrameArray, DIRECT3DRMFRAMEARRAY); -WIN_TYPES(IDirect3DRMVisualArray, DIRECT3DRMVISUALARRAY); -WIN_TYPES(IDirect3DRMPickedArray, DIRECT3DRMPICKEDARRAY); -WIN_TYPES(IDirect3DRMLightArray, DIRECT3DRMLIGHTARRAY); - -/* - * Direct3DRM Object classes - */ -DEFINE_GUID(CLSID_CDirect3DRMDevice, 0x4fa3568e, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMViewport, 0x4fa3568f, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMFrame, 0x4fa35690, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMMesh, 0x4fa35691, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMMeshBuilder, 0x4fa35692, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMFace, 0x4fa35693, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMLight, 0x4fa35694, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMTexture, 0x4fa35695, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMWrap, 0x4fa35696, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMMaterial, 0x4fa35697, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMAnimation, 0x4fa35698, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMAnimationSet, 0x4fa35699, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMUserVisual, 0x4fa3569a, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(CLSID_CDirect3DRMShadow, 0x4fa3569b, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); - -/* - * Direct3DRM Object interfaces - */ -DEFINE_GUID(IID_IDirect3DRMObject, 0xeb16cb00, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMDevice, 0xe9e19280, 0x6e05, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMViewport, 0xeb16cb02, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMFrame, 0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMVisual, 0xeb16cb04, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMMesh, 0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMMeshBuilder, 0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMFace, 0xeb16cb07, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMLight, 0xeb16cb08, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMTexture, 0xeb16cb09, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMWrap, 0xeb16cb0a, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMMaterial, 0xeb16cb0b, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMAnimation, 0xeb16cb0d, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMAnimationSet, 0xeb16cb0e, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMDeviceArray, 0xeb16cb10, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMViewportArray, 0xeb16cb11, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMFrameArray, 0xeb16cb12, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMVisualArray, 0xeb16cb13, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMLightArray, 0xeb16cb14, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMPickedArray, 0xeb16cb16, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMFaceArray, 0xeb16cb17, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMUserVisual, 0x59163de0, 0x6d43, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); -DEFINE_GUID(IID_IDirect3DRMShadow, 0xaf359780, 0x6ba3, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); - -typedef void (*D3DRMOBJECTCALLBACK)(LPDIRECT3DRMOBJECT obj, LPVOID arg); -typedef void (*D3DRMFRAMEMOVECALLBACK)(LPDIRECT3DRMFRAME obj, LPVOID arg, D3DVALUE delta); -typedef void (*D3DRMUPDATECALLBACK)(LPDIRECT3DRMDEVICE obj, LPVOID arg, int, LPD3DRECT); -typedef int (*D3DRMUSERVISUALCALLBACK)(LPDIRECT3DRMUSERVISUAL obj, LPVOID arg, - D3DRMUSERVISUALREASON reason, - LPDIRECT3DRMDEVICE dev, - LPDIRECT3DRMVIEWPORT view); -typedef HRESULT (*D3DRMLOADTEXTURECALLBACK) - (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE *); -typedef void (*D3DRMLOADCALLBACK) - (LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg); - - - -typedef struct _D3DRMPICKDESC -{ - ULONG ulFaceIdx; - LONG lGroupIdx; - D3DVECTOR vPosition; - -} D3DRMPICKDESC, *LPD3DRMPICKDESC; - -#undef INTERFACE -#define INTERFACE IDirect3DRMObject - -/* - * Base class - */ -DECLARE_INTERFACE_(IDirect3DRMObject, IUnknown) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMVisual - -DECLARE_INTERFACE_(IDirect3DRMVisual, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMDevice - -DECLARE_INTERFACE_(IDirect3DRMDevice, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMDevice methods - */ - STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE; - STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE; - STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE; - - STDMETHOD(Update)(THIS) PURE; - STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE; - STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE; - STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE; - STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE; - - STDMETHOD(SetDither)(THIS_ BOOL) PURE; - STDMETHOD(SetShades)(THIS_ DWORD) PURE; - STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE; - STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE; - - STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE; - - STDMETHOD_(BOOL, GetDither)(THIS) PURE; - STDMETHOD_(DWORD, GetShades)(THIS) PURE; - STDMETHOD_(DWORD, GetHeight)(THIS) PURE; - STDMETHOD_(DWORD, GetWidth)(THIS) PURE; - STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE; - STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE; - STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE; - STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE; - STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE; - STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMViewport - -DECLARE_INTERFACE_(IDirect3DRMViewport, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMViewport methods - */ - STDMETHOD(Init) - ( THIS_ LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMFRAME camera, - DWORD xpos, DWORD ypos, DWORD width, DWORD height - ) PURE; - STDMETHOD(Clear)(THIS) PURE; - STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME) PURE; - - STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetField)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE; - STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME) PURE; - STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE; - STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE; - STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE; - STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE; - STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE; - STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE; - - STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME *) PURE; - STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE *) PURE; - STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE; - STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE; - - STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE; - STDMETHOD_(LONG, GetX)(THIS) PURE; - STDMETHOD_(LONG, GetY)(THIS) PURE; - STDMETHOD_(DWORD, GetWidth)(THIS) PURE; - STDMETHOD_(DWORD, GetHeight)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetField)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE; - STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE; - STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMFrame - -DECLARE_INTERFACE_(IDirect3DRMFrame, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMFrame methods - */ - STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE; - STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE; - STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE; - STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE; - STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; - STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE; - STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE; - STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE; - STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; - STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE; - STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE; - STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE; - STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE; - STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE; - STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE; - STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE; - STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE; - STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE; - STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE; - STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE; - STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE; - STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE; - STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE; - STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE; - STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE; - STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE; - STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE; - STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE; - STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE; - STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE; - STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE; - STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE; - STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE; - STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE; - STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE; - STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE; - STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE; - STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE; - STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE; - STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE; - STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE; - STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE; - STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE; - STDMETHOD(SetOrientation) - ( THIS_ LPDIRECT3DRMFRAME reference, - D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, - D3DVALUE ux, D3DVALUE uy, D3DVALUE uz - ) PURE; - STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE; - STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE; - STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; - STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; - STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE; - STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE; - STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMMesh - -DECLARE_INTERFACE_(IDirect3DRMMesh, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMMesh methods - */ - STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; - STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE; - STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE; - STDMETHOD(AddGroup)(THIS_ unsigned vCount, unsigned fCount, unsigned vPerFace, unsigned *fData, D3DRMGROUPINDEX *returnId) PURE; - STDMETHOD(SetVertices)(THIS_ D3DRMGROUPINDEX id, unsigned index, unsigned count, D3DRMVERTEX *values) PURE; - STDMETHOD(SetGroupColor)(THIS_ D3DRMGROUPINDEX id, D3DCOLOR value) PURE; - STDMETHOD(SetGroupColorRGB)(THIS_ D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - STDMETHOD(SetGroupMapping)(THIS_ D3DRMGROUPINDEX id, D3DRMMAPPING value) PURE; - STDMETHOD(SetGroupQuality)(THIS_ D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value) PURE; - STDMETHOD(SetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL value) PURE; - STDMETHOD(SetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE value) PURE; - - STDMETHOD_(unsigned, GetGroupCount)(THIS) PURE; - STDMETHOD(GetGroup)(THIS_ D3DRMGROUPINDEX id, unsigned *vCount, unsigned *fCount, unsigned *vPerFace, DWORD *fDataSize, unsigned *fData) PURE; - STDMETHOD(GetVertices)(THIS_ D3DRMGROUPINDEX id, DWORD index, DWORD count, D3DRMVERTEX *returnPtr) PURE; - STDMETHOD_(D3DCOLOR, GetGroupColor)(THIS_ D3DRMGROUPINDEX id) PURE; - STDMETHOD_(D3DRMMAPPING, GetGroupMapping)(THIS_ D3DRMGROUPINDEX id) PURE; - STDMETHOD_(D3DRMRENDERQUALITY, GetGroupQuality)(THIS_ D3DRMGROUPINDEX id) PURE; - STDMETHOD(GetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL *returnPtr) PURE; - STDMETHOD(GetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE *returnPtr) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMShadow - -DECLARE_INTERFACE_(IDirect3DRMShadow, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMShadow methods - */ - STDMETHOD(Init) - ( THIS_ LPDIRECT3DRMVISUAL visual, LPDIRECT3DRMLIGHT light, - D3DVALUE px, D3DVALUE py, D3DVALUE pz, - D3DVALUE nx, D3DVALUE ny, D3DVALUE nz - ) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMFace - -DECLARE_INTERFACE_(IDirect3DRMFace, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMFace methods - */ - STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE; - STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE; - STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; - STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE; - STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE; - STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; - - STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE; - STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals); - STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE; - STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE; - STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE; - STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE; - STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE; - - STDMETHOD_(int, GetVertexCount)(THIS) PURE; - STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE; - STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE; - STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMMeshBuilder - -DECLARE_INTERFACE_(IDirect3DRMMeshBuilder, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMMeshBuilder methods - */ - STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE; - STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE; - STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; - STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE; - STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE; - STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE; - STDMETHOD(GenerateNormals)(THIS) PURE; - STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE; - - STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE; - STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE; - STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE; - STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE; - STDMETHOD(AddFaces) - ( THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals, - DWORD *data, LPDIRECT3DRMFACEARRAY* - ) PURE; - STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE; - STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; - STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE; - STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; - STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE; - STDMETHOD(SetPerspective)(THIS_ BOOL) PURE; - STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE; - STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE; - STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - - STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE; - STDMETHOD(GetVertices) - ( THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data - ) PURE; - STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE; - - STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE; - STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE; - STDMETHOD_(BOOL, GetPerspective)(THIS) PURE; - STDMETHOD_(int, GetFaceCount)(THIS) PURE; - STDMETHOD_(int, GetVertexCount)(THIS) PURE; - STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE; - - STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMLight - -DECLARE_INTERFACE_(IDirect3DRMLight, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMLight methods - */ - STDMETHOD(SetType)(THIS_ D3DRMLIGHTTYPE) PURE; - STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; - STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; - STDMETHOD(SetRange)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetUmbra)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetPenumbra)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetConstantAttenuation)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetLinearAttenuation)(THIS_ D3DVALUE) PURE; - STDMETHOD(SetQuadraticAttenuation)(THIS_ D3DVALUE) PURE; - - STDMETHOD_(D3DVALUE, GetRange)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetUmbra)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetPenumbra)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetConstantAttenuation)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetLinearAttenuation)(THIS) PURE; - STDMETHOD_(D3DVALUE, GetQuadraticAttenuation)(THIS) PURE; - STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; - STDMETHOD_(D3DRMLIGHTTYPE, GetType)(THIS) PURE; - - STDMETHOD(SetEnableFrame)(THIS_ LPDIRECT3DRMFRAME) PURE; - STDMETHOD(GetEnableFrame)(THIS_ LPDIRECT3DRMFRAME*) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMTexture - -DECLARE_INTERFACE_(IDirect3DRMTexture, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMTexture methods - */ - STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE; - STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE; - STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE; - STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE; - - STDMETHOD(SetColors)(THIS_ DWORD) PURE; - STDMETHOD(SetShades)(THIS_ DWORD) PURE; - STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE; - STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE; - STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE; - STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE; - STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE; - - STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE; - STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE; - - STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE; - STDMETHOD_(DWORD, GetShades)(THIS) PURE; - STDMETHOD_(DWORD, GetColors)(THIS) PURE; - STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE; - STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE; - STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMWrap - -DECLARE_INTERFACE_(IDirect3DRMWrap, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMWrap methods - */ - STDMETHOD(Init) - ( THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME ref, - D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, - D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, - D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, - D3DVALUE ou, D3DVALUE ov, - D3DVALUE su, D3DVALUE sv - ) PURE; - STDMETHOD(Apply)(THIS_ LPDIRECT3DRMOBJECT) PURE; - STDMETHOD(ApplyRelative)(THIS_ LPDIRECT3DRMFRAME frame, LPDIRECT3DRMOBJECT) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMMaterial - -DECLARE_INTERFACE_(IDirect3DRMMaterial, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMMaterial methods - */ - STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE; - STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE; - STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE; - - STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE; - STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE; - STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMAnimation - -DECLARE_INTERFACE_(IDirect3DRMAnimation, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMAnimation methods - */ - STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE; - STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE; - STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; - STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE; - STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME frame) PURE; - STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE; - - STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMAnimationSet - -DECLARE_INTERFACE_(IDirect3DRMAnimationSet, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMAnimationSet methods - */ - STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE; - STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME parent)PURE; - STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE; - STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMUserVisual - -DECLARE_INTERFACE_(IDirect3DRMUserVisual, IDirect3DRMVisual) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMUserVisual methods - */ - STDMETHOD(Init)(THIS_ D3DRMUSERVISUALCALLBACK fn, void *arg) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMArray - -DECLARE_INTERFACE_(IDirect3DRMArray, IUnknown) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - /* No GetElement method as it would get overloaded - * in derived classes, and overloading is - * a no-no in COM - */ -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMDeviceArray - -DECLARE_INTERFACE_(IDirect3DRMDeviceArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMDEVICE *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMFrameArray - -DECLARE_INTERFACE_(IDirect3DRMFrameArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFRAME *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMViewportArray - -DECLARE_INTERFACE_(IDirect3DRMViewportArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVIEWPORT *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMVisualArray - -DECLARE_INTERFACE_(IDirect3DRMVisualArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMPickedArray - -DECLARE_INTERFACE_(IDirect3DRMPickedArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMLightArray - -DECLARE_INTERFACE_(IDirect3DRMLightArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMLIGHT *) PURE; -}; - -#undef INTERFACE -#define INTERFACE IDirect3DRMFaceArray - -DECLARE_INTERFACE_(IDirect3DRMFaceArray, IDirect3DRMArray) -{ - IUNKNOWN_METHODS(PURE); - - STDMETHOD_(DWORD, GetSize)(THIS) PURE; - STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFACE *) PURE; -}; - -#ifdef __cplusplus -}; -#endif -#endif /* _D3DRMOBJ_H_ */ +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3drm.h + * Content: Direct3DRM include file + * + ***************************************************************************/ + +#ifndef _D3DRMOBJ_H_ +#define _D3DRMOBJ_H_ + +#include /* Use Windows header files */ +#define VIRTUAL + +#include "d3drmdef.h" +#include "d3d.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The methods for IUnknown + */ +#define IUNKNOWN_METHODS(kind) \ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) kind; \ + STDMETHOD_(ULONG, AddRef) (THIS) kind; \ + STDMETHOD_(ULONG, Release) (THIS) kind + +/* + * The methods for IDirect3DRMObject + */ +#define IDIRECT3DRMOBJECT_METHODS(kind) \ + STDMETHOD(Clone) (THIS_ LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) kind; \ + STDMETHOD(AddDestroyCallback) (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \ + STDMETHOD(DeleteDestroyCallback) (THIS_ D3DRMOBJECTCALLBACK, LPVOID argument) kind; \ + STDMETHOD(SetAppData) (THIS_ DWORD data) kind; \ + STDMETHOD_(DWORD, GetAppData) (THIS) kind; \ + STDMETHOD(SetName) (THIS_ LPCSTR) kind; \ + STDMETHOD(GetName) (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind; \ + STDMETHOD(GetClassName) (THIS_ LPDWORD lpdwSize, LPSTR lpName) kind + + +#define WIN_TYPES(itype, ptype) \ + typedef interface itype FAR *LP##ptype, FAR **LPLP##ptype + +WIN_TYPES(IDirect3DRMObject, DIRECT3DRMOBJECT); +WIN_TYPES(IDirect3DRMDevice, DIRECT3DRMDEVICE); +WIN_TYPES(IDirect3DRMViewport, DIRECT3DRMVIEWPORT); +WIN_TYPES(IDirect3DRMFrame, DIRECT3DRMFRAME); +WIN_TYPES(IDirect3DRMVisual, DIRECT3DRMVISUAL); +WIN_TYPES(IDirect3DRMMesh, DIRECT3DRMMESH); +WIN_TYPES(IDirect3DRMMeshBuilder, DIRECT3DRMMESHBUILDER); +WIN_TYPES(IDirect3DRMFace, DIRECT3DRMFACE); +WIN_TYPES(IDirect3DRMLight, DIRECT3DRMLIGHT); +WIN_TYPES(IDirect3DRMTexture, DIRECT3DRMTEXTURE); +WIN_TYPES(IDirect3DRMWrap, DIRECT3DRMWRAP); +WIN_TYPES(IDirect3DRMMaterial, DIRECT3DRMMATERIAL); +WIN_TYPES(IDirect3DRMAnimation, DIRECT3DRMANIMATION); +WIN_TYPES(IDirect3DRMAnimationSet, DIRECT3DRMANIMATIONSET); +WIN_TYPES(IDirect3DRMUserVisual, DIRECT3DRMUSERVISUAL); +WIN_TYPES(IDirect3DRMShadow, DIRECT3DRMSHADOW); +WIN_TYPES(IDirect3DRMArray, DIRECT3DRMOBJECTARRAY); +WIN_TYPES(IDirect3DRMDeviceArray, DIRECT3DRMDEVICEARRAY); +WIN_TYPES(IDirect3DRMFaceArray, DIRECT3DRMFACEARRAY); +WIN_TYPES(IDirect3DRMViewportArray, DIRECT3DRMVIEWPORTARRAY); +WIN_TYPES(IDirect3DRMFrameArray, DIRECT3DRMFRAMEARRAY); +WIN_TYPES(IDirect3DRMVisualArray, DIRECT3DRMVISUALARRAY); +WIN_TYPES(IDirect3DRMPickedArray, DIRECT3DRMPICKEDARRAY); +WIN_TYPES(IDirect3DRMLightArray, DIRECT3DRMLIGHTARRAY); + +/* + * Direct3DRM Object classes + */ +DEFINE_GUID(CLSID_CDirect3DRMDevice, 0x4fa3568e, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMViewport, 0x4fa3568f, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMFrame, 0x4fa35690, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMMesh, 0x4fa35691, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMMeshBuilder, 0x4fa35692, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMFace, 0x4fa35693, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMLight, 0x4fa35694, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMTexture, 0x4fa35695, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMWrap, 0x4fa35696, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMMaterial, 0x4fa35697, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMAnimation, 0x4fa35698, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMAnimationSet, 0x4fa35699, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMUserVisual, 0x4fa3569a, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(CLSID_CDirect3DRMShadow, 0x4fa3569b, 0x623f, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); + +/* + * Direct3DRM Object interfaces + */ +DEFINE_GUID(IID_IDirect3DRMObject, 0xeb16cb00, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMDevice, 0xe9e19280, 0x6e05, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMViewport, 0xeb16cb02, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMFrame, 0xeb16cb03, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMVisual, 0xeb16cb04, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMMesh, 0xa3a80d01, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMMeshBuilder, 0xa3a80d02, 0x6e12, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMFace, 0xeb16cb07, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMLight, 0xeb16cb08, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMTexture, 0xeb16cb09, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMWrap, 0xeb16cb0a, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMMaterial, 0xeb16cb0b, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMAnimation, 0xeb16cb0d, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMAnimationSet, 0xeb16cb0e, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMDeviceArray, 0xeb16cb10, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMViewportArray, 0xeb16cb11, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMFrameArray, 0xeb16cb12, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMVisualArray, 0xeb16cb13, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMLightArray, 0xeb16cb14, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMPickedArray, 0xeb16cb16, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMFaceArray, 0xeb16cb17, 0xd271, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMUserVisual, 0x59163de0, 0x6d43, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); +DEFINE_GUID(IID_IDirect3DRMShadow, 0xaf359780, 0x6ba3, 0x11cf, 0xac, 0x4a, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); + +typedef void (*D3DRMOBJECTCALLBACK)(LPDIRECT3DRMOBJECT obj, LPVOID arg); +typedef void (*D3DRMFRAMEMOVECALLBACK)(LPDIRECT3DRMFRAME obj, LPVOID arg, D3DVALUE delta); +typedef void (*D3DRMUPDATECALLBACK)(LPDIRECT3DRMDEVICE obj, LPVOID arg, int, LPD3DRECT); +typedef int (*D3DRMUSERVISUALCALLBACK)(LPDIRECT3DRMUSERVISUAL obj, LPVOID arg, + D3DRMUSERVISUALREASON reason, + LPDIRECT3DRMDEVICE dev, + LPDIRECT3DRMVIEWPORT view); +typedef HRESULT (*D3DRMLOADTEXTURECALLBACK) + (char *tex_name, void *arg, LPDIRECT3DRMTEXTURE *); +typedef void (*D3DRMLOADCALLBACK) + (LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg); + + + +typedef struct _D3DRMPICKDESC +{ + ULONG ulFaceIdx; + LONG lGroupIdx; + D3DVECTOR vPosition; + +} D3DRMPICKDESC, *LPD3DRMPICKDESC; + +#undef INTERFACE +#define INTERFACE IDirect3DRMObject + +/* + * Base class + */ +DECLARE_INTERFACE_(IDirect3DRMObject, IUnknown) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMVisual + +DECLARE_INTERFACE_(IDirect3DRMVisual, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMDevice + +DECLARE_INTERFACE_(IDirect3DRMDevice, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMDevice methods + */ + STDMETHOD(Init)(THIS_ ULONG width, ULONG height) PURE; + STDMETHOD(InitFromD3D)(THIS_ LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpD3DDev) PURE; + STDMETHOD(InitFromClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper, LPGUID lpGUID, int width, int height) PURE; + + STDMETHOD(Update)(THIS) PURE; + STDMETHOD(AddUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE; + STDMETHOD(DeleteUpdateCallback)(THIS_ D3DRMUPDATECALLBACK, LPVOID arg) PURE; + STDMETHOD(SetBufferCount)(THIS_ DWORD) PURE; + STDMETHOD_(DWORD, GetBufferCount)(THIS) PURE; + + STDMETHOD(SetDither)(THIS_ BOOL) PURE; + STDMETHOD(SetShades)(THIS_ DWORD) PURE; + STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE; + STDMETHOD(SetTextureQuality)(THIS_ D3DRMTEXTUREQUALITY) PURE; + + STDMETHOD(GetViewports)(THIS_ LPDIRECT3DRMVIEWPORTARRAY *return_views) PURE; + + STDMETHOD_(BOOL, GetDither)(THIS) PURE; + STDMETHOD_(DWORD, GetShades)(THIS) PURE; + STDMETHOD_(DWORD, GetHeight)(THIS) PURE; + STDMETHOD_(DWORD, GetWidth)(THIS) PURE; + STDMETHOD_(DWORD, GetTrianglesDrawn)(THIS) PURE; + STDMETHOD_(DWORD, GetWireframeOptions)(THIS) PURE; + STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE; + STDMETHOD_(D3DCOLORMODEL, GetColorModel)(THIS) PURE; + STDMETHOD_(D3DRMTEXTUREQUALITY, GetTextureQuality)(THIS) PURE; + STDMETHOD(GetDirect3DDevice)(THIS_ LPDIRECT3DDEVICE *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMViewport + +DECLARE_INTERFACE_(IDirect3DRMViewport, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMViewport methods + */ + STDMETHOD(Init) + ( THIS_ LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMFRAME camera, + DWORD xpos, DWORD ypos, DWORD width, DWORD height + ) PURE; + STDMETHOD(Clear)(THIS) PURE; + STDMETHOD(Render)(THIS_ LPDIRECT3DRMFRAME) PURE; + + STDMETHOD(SetFront)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetBack)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetField)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetUniformScaling)(THIS_ BOOL) PURE; + STDMETHOD(SetCamera)(THIS_ LPDIRECT3DRMFRAME) PURE; + STDMETHOD(SetProjection)(THIS_ D3DRMPROJECTIONTYPE) PURE; + STDMETHOD(Transform)(THIS_ D3DRMVECTOR4D *d, D3DVECTOR *s) PURE; + STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DRMVECTOR4D *s) PURE; + STDMETHOD(Configure)(THIS_ LONG x, LONG y, DWORD width, DWORD height) PURE; + STDMETHOD(ForceUpdate)(THIS_ DWORD x1, DWORD y1, DWORD x2, DWORD y2) PURE; + STDMETHOD(SetPlane)(THIS_ D3DVALUE left, D3DVALUE right, D3DVALUE bottom, D3DVALUE top) PURE; + + STDMETHOD(GetCamera)(THIS_ LPDIRECT3DRMFRAME *) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DRMDEVICE *) PURE; + STDMETHOD(GetPlane)(THIS_ D3DVALUE *left, D3DVALUE *right, D3DVALUE *bottom, D3DVALUE *top) PURE; + STDMETHOD(Pick)(THIS_ LONG x, LONG y, LPDIRECT3DRMPICKEDARRAY *return_visuals) PURE; + + STDMETHOD_(BOOL, GetUniformScaling)(THIS) PURE; + STDMETHOD_(LONG, GetX)(THIS) PURE; + STDMETHOD_(LONG, GetY)(THIS) PURE; + STDMETHOD_(DWORD, GetWidth)(THIS) PURE; + STDMETHOD_(DWORD, GetHeight)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetField)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetBack)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetFront)(THIS) PURE; + STDMETHOD_(D3DRMPROJECTIONTYPE, GetProjection)(THIS) PURE; + STDMETHOD(GetDirect3DViewport)(THIS_ LPDIRECT3DVIEWPORT *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMFrame + +DECLARE_INTERFACE_(IDirect3DRMFrame, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMFrame methods + */ + STDMETHOD(AddChild)(THIS_ LPDIRECT3DRMFRAME child) PURE; + STDMETHOD(AddLight)(THIS_ LPDIRECT3DRMLIGHT) PURE; + STDMETHOD(AddMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE; + STDMETHOD(AddTransform)(THIS_ D3DRMCOMBINETYPE, D3DRMMATRIX4D) PURE; + STDMETHOD(AddTranslation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(AddScale)(THIS_ D3DRMCOMBINETYPE, D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; + STDMETHOD(AddRotation)(THIS_ D3DRMCOMBINETYPE, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE; + STDMETHOD(AddVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE; + STDMETHOD(GetChildren)(THIS_ LPDIRECT3DRMFRAMEARRAY *children) PURE; + STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; + STDMETHOD(GetLights)(THIS_ LPDIRECT3DRMLIGHTARRAY *lights) PURE; + STDMETHOD_(D3DRMMATERIALMODE, GetMaterialMode)(THIS) PURE; + STDMETHOD(GetParent)(THIS_ LPDIRECT3DRMFRAME *) PURE; + STDMETHOD(GetPosition)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_position) PURE; + STDMETHOD(GetRotation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR axis, LPD3DVALUE return_theta) PURE; + STDMETHOD(GetScene)(THIS_ LPDIRECT3DRMFRAME *) PURE; + STDMETHOD_(D3DRMSORTMODE, GetSortMode)(THIS) PURE; + STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE; + STDMETHOD(GetTransform)(THIS_ D3DRMMATRIX4D return_matrix) PURE; + STDMETHOD(GetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR return_velocity, BOOL with_rotation) PURE; + STDMETHOD(GetOrientation)(THIS_ LPDIRECT3DRMFRAME reference, LPD3DVECTOR dir, LPD3DVECTOR up) PURE; + STDMETHOD(GetVisuals)(THIS_ LPDIRECT3DRMVISUALARRAY *visuals) PURE; + STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE; + STDMETHOD(InverseTransform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE; + STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg)PURE; + STDMETHOD(LookAt)(THIS_ LPDIRECT3DRMFRAME target, LPDIRECT3DRMFRAME reference, D3DRMFRAMECONSTRAINT) PURE; + STDMETHOD(Move)(THIS_ D3DVALUE delta) PURE; + STDMETHOD(DeleteChild)(THIS_ LPDIRECT3DRMFRAME) PURE; + STDMETHOD(DeleteLight)(THIS_ LPDIRECT3DRMLIGHT) PURE; + STDMETHOD(DeleteMoveCallback)(THIS_ D3DRMFRAMEMOVECALLBACK, VOID *arg) PURE; + STDMETHOD(DeleteVisual)(THIS_ LPDIRECT3DRMVISUAL) PURE; + STDMETHOD_(D3DCOLOR, GetSceneBackground)(THIS) PURE; + STDMETHOD(GetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE *) PURE; + STDMETHOD_(D3DCOLOR, GetSceneFogColor)(THIS) PURE; + STDMETHOD_(BOOL, GetSceneFogEnable)(THIS) PURE; + STDMETHOD_(D3DRMFOGMODE, GetSceneFogMode)(THIS) PURE; + STDMETHOD(GetSceneFogParams)(THIS_ D3DVALUE *return_start, D3DVALUE *return_end, D3DVALUE *return_density) PURE; + STDMETHOD(SetSceneBackground)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetSceneBackgroundRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + STDMETHOD(SetSceneBackgroundDepth)(THIS_ LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(SetSceneBackgroundImage)(THIS_ LPDIRECT3DRMTEXTURE) PURE; + STDMETHOD(SetSceneFogEnable)(THIS_ BOOL) PURE; + STDMETHOD(SetSceneFogColor)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetSceneFogMode)(THIS_ D3DRMFOGMODE) PURE; + STDMETHOD(SetSceneFogParams)(THIS_ D3DVALUE start, D3DVALUE end, D3DVALUE density) PURE; + STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + STDMETHOD_(D3DRMZBUFFERMODE, GetZbufferMode)(THIS) PURE; + STDMETHOD(SetMaterialMode)(THIS_ D3DRMMATERIALMODE) PURE; + STDMETHOD(SetOrientation) + ( THIS_ LPDIRECT3DRMFRAME reference, + D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, + D3DVALUE ux, D3DVALUE uy, D3DVALUE uz + ) PURE; + STDMETHOD(SetPosition)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(SetRotation)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, D3DVALUE theta) PURE; + STDMETHOD(SetSortMode)(THIS_ D3DRMSORTMODE) PURE; + STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; + STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; + STDMETHOD(SetVelocity)(THIS_ LPDIRECT3DRMFRAME reference, D3DVALUE x, D3DVALUE y, D3DVALUE z, BOOL with_rotation) PURE; + STDMETHOD(SetZbufferMode)(THIS_ D3DRMZBUFFERMODE) PURE; + STDMETHOD(Transform)(THIS_ D3DVECTOR *d, D3DVECTOR *s) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMMesh + +DECLARE_INTERFACE_(IDirect3DRMMesh, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMMesh methods + */ + STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; + STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE; + STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE; + STDMETHOD(AddGroup)(THIS_ unsigned vCount, unsigned fCount, unsigned vPerFace, unsigned *fData, D3DRMGROUPINDEX *returnId) PURE; + STDMETHOD(SetVertices)(THIS_ D3DRMGROUPINDEX id, unsigned index, unsigned count, D3DRMVERTEX *values) PURE; + STDMETHOD(SetGroupColor)(THIS_ D3DRMGROUPINDEX id, D3DCOLOR value) PURE; + STDMETHOD(SetGroupColorRGB)(THIS_ D3DRMGROUPINDEX id, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + STDMETHOD(SetGroupMapping)(THIS_ D3DRMGROUPINDEX id, D3DRMMAPPING value) PURE; + STDMETHOD(SetGroupQuality)(THIS_ D3DRMGROUPINDEX id, D3DRMRENDERQUALITY value) PURE; + STDMETHOD(SetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL value) PURE; + STDMETHOD(SetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE value) PURE; + + STDMETHOD_(unsigned, GetGroupCount)(THIS) PURE; + STDMETHOD(GetGroup)(THIS_ D3DRMGROUPINDEX id, unsigned *vCount, unsigned *fCount, unsigned *vPerFace, DWORD *fDataSize, unsigned *fData) PURE; + STDMETHOD(GetVertices)(THIS_ D3DRMGROUPINDEX id, DWORD index, DWORD count, D3DRMVERTEX *returnPtr) PURE; + STDMETHOD_(D3DCOLOR, GetGroupColor)(THIS_ D3DRMGROUPINDEX id) PURE; + STDMETHOD_(D3DRMMAPPING, GetGroupMapping)(THIS_ D3DRMGROUPINDEX id) PURE; + STDMETHOD_(D3DRMRENDERQUALITY, GetGroupQuality)(THIS_ D3DRMGROUPINDEX id) PURE; + STDMETHOD(GetGroupMaterial)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMMATERIAL *returnPtr) PURE; + STDMETHOD(GetGroupTexture)(THIS_ D3DRMGROUPINDEX id, LPDIRECT3DRMTEXTURE *returnPtr) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMShadow + +DECLARE_INTERFACE_(IDirect3DRMShadow, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMShadow methods + */ + STDMETHOD(Init) + ( THIS_ LPDIRECT3DRMVISUAL visual, LPDIRECT3DRMLIGHT light, + D3DVALUE px, D3DVALUE py, D3DVALUE pz, + D3DVALUE nx, D3DVALUE ny, D3DVALUE nz + ) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMFace + +DECLARE_INTERFACE_(IDirect3DRMFace, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMFace methods + */ + STDMETHOD(AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(AddVertexAndNormalIndexed)(THIS_ DWORD vertex, DWORD normal) PURE; + STDMETHOD(SetColorRGB)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE) PURE; + STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; + STDMETHOD(SetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE u, D3DVALUE v) PURE; + STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE; + STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; + + STDMETHOD(GetVertex)(THIS_ DWORD index, D3DVECTOR *vertex, D3DVECTOR *normal) PURE; + STDMETHOD(GetVertices)(THIS_ DWORD *vertex_count, D3DVECTOR *coords, D3DVECTOR *normals); + STDMETHOD(GetTextureCoordinates)(THIS_ DWORD vertex, D3DVALUE *u, D3DVALUE *v) PURE; + STDMETHOD(GetTextureTopology)(THIS_ BOOL *wrap_u, BOOL *wrap_v) PURE; + STDMETHOD(GetNormal)(THIS_ D3DVECTOR *) PURE; + STDMETHOD(GetTexture)(THIS_ LPDIRECT3DRMTEXTURE *) PURE; + STDMETHOD(GetMaterial)(THIS_ LPDIRECT3DRMMATERIAL *) PURE; + + STDMETHOD_(int, GetVertexCount)(THIS) PURE; + STDMETHOD_(int, GetVertexIndex)(THIS_ DWORD which) PURE; + STDMETHOD_(int, GetTextureCoordinateIndex)(THIS_ DWORD which) PURE; + STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMMeshBuilder + +DECLARE_INTERFACE_(IDirect3DRMMeshBuilder, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMMeshBuilder methods + */ + STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg) PURE; + STDMETHOD(Save)(THIS_ const char *filename, D3DRMXOFFORMAT, D3DRMSAVEOPTIONS save) PURE; + STDMETHOD(Scale)(THIS_ D3DVALUE sx, D3DVALUE sy, D3DVALUE sz) PURE; + STDMETHOD(Translate)(THIS_ D3DVALUE tx, D3DVALUE ty, D3DVALUE tz) PURE; + STDMETHOD(SetColorSource)(THIS_ D3DRMCOLORSOURCE) PURE; + STDMETHOD(GetBox)(THIS_ D3DRMBOX *) PURE; + STDMETHOD(GenerateNormals)(THIS) PURE; + STDMETHOD_(D3DRMCOLORSOURCE, GetColorSource)(THIS) PURE; + + STDMETHOD(AddMesh)(THIS_ LPDIRECT3DRMMESH) PURE; + STDMETHOD(AddMeshBuilder)(THIS_ LPDIRECT3DRMMESHBUILDER) PURE; + STDMETHOD(AddFrame)(THIS_ LPDIRECT3DRMFRAME) PURE; + STDMETHOD(AddFace)(THIS_ LPDIRECT3DRMFACE) PURE; + STDMETHOD(AddFaces) + ( THIS_ DWORD vcount, D3DVECTOR *vertices, DWORD ncount, D3DVECTOR *normals, + DWORD *data, LPDIRECT3DRMFACEARRAY* + ) PURE; + STDMETHOD(ReserveSpace)(THIS_ DWORD vertex_Count, DWORD normal_count, DWORD face_count) PURE; + STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetTexture)(THIS_ LPDIRECT3DRMTEXTURE) PURE; + STDMETHOD(SetMaterial)(THIS_ LPDIRECT3DRMMATERIAL) PURE; + STDMETHOD(SetTextureTopology)(THIS_ BOOL wrap_u, BOOL wrap_v) PURE; + STDMETHOD(SetQuality)(THIS_ D3DRMRENDERQUALITY) PURE; + STDMETHOD(SetPerspective)(THIS_ BOOL) PURE; + STDMETHOD(SetVertex)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(SetNormal)(THIS_ DWORD index, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(SetTextureCoordinates)(THIS_ DWORD index, D3DVALUE u, D3DVALUE v) PURE; + STDMETHOD(SetVertexColor)(THIS_ DWORD index, D3DCOLOR) PURE; + STDMETHOD(SetVertexColorRGB)(THIS_ DWORD index, D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + + STDMETHOD(GetFaces)(THIS_ LPDIRECT3DRMFACEARRAY*) PURE; + STDMETHOD(GetVertices) + ( THIS_ DWORD *vcount, D3DVECTOR *vertices, DWORD *ncount, D3DVECTOR *normals, DWORD *face_data_size, DWORD *face_data + ) PURE; + STDMETHOD(GetTextureCoordinates)(THIS_ DWORD index, D3DVALUE *u, D3DVALUE *v) PURE; + + STDMETHOD_(int, AddVertex)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD_(int, AddNormal)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(CreateFace)(THIS_ LPDIRECT3DRMFACE*) PURE; + STDMETHOD_(D3DRMRENDERQUALITY, GetQuality)(THIS) PURE; + STDMETHOD_(BOOL, GetPerspective)(THIS) PURE; + STDMETHOD_(int, GetFaceCount)(THIS) PURE; + STDMETHOD_(int, GetVertexCount)(THIS) PURE; + STDMETHOD_(D3DCOLOR, GetVertexColor)(THIS_ DWORD index) PURE; + + STDMETHOD(CreateMesh)(THIS_ LPDIRECT3DRMMESH*) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMLight + +DECLARE_INTERFACE_(IDirect3DRMLight, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMLight methods + */ + STDMETHOD(SetType)(THIS_ D3DRMLIGHTTYPE) PURE; + STDMETHOD(SetColor)(THIS_ D3DCOLOR) PURE; + STDMETHOD(SetColorRGB)(THIS_ D3DVALUE red, D3DVALUE green, D3DVALUE blue) PURE; + STDMETHOD(SetRange)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetUmbra)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetPenumbra)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetConstantAttenuation)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetLinearAttenuation)(THIS_ D3DVALUE) PURE; + STDMETHOD(SetQuadraticAttenuation)(THIS_ D3DVALUE) PURE; + + STDMETHOD_(D3DVALUE, GetRange)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetUmbra)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetPenumbra)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetConstantAttenuation)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetLinearAttenuation)(THIS) PURE; + STDMETHOD_(D3DVALUE, GetQuadraticAttenuation)(THIS) PURE; + STDMETHOD_(D3DCOLOR, GetColor)(THIS) PURE; + STDMETHOD_(D3DRMLIGHTTYPE, GetType)(THIS) PURE; + + STDMETHOD(SetEnableFrame)(THIS_ LPDIRECT3DRMFRAME) PURE; + STDMETHOD(GetEnableFrame)(THIS_ LPDIRECT3DRMFRAME*) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMTexture + +DECLARE_INTERFACE_(IDirect3DRMTexture, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMTexture methods + */ + STDMETHOD(InitFromFile)(THIS_ const char *filename) PURE; + STDMETHOD(InitFromSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDS) PURE; + STDMETHOD(InitFromResource)(THIS_ HRSRC) PURE; + STDMETHOD(Changed)(THIS_ BOOL pixels, BOOL palette) PURE; + + STDMETHOD(SetColors)(THIS_ DWORD) PURE; + STDMETHOD(SetShades)(THIS_ DWORD) PURE; + STDMETHOD(SetDecalSize)(THIS_ D3DVALUE width, D3DVALUE height) PURE; + STDMETHOD(SetDecalOrigin)(THIS_ LONG x, LONG y) PURE; + STDMETHOD(SetDecalScale)(THIS_ DWORD) PURE; + STDMETHOD(SetDecalTransparency)(THIS_ BOOL) PURE; + STDMETHOD(SetDecalTransparentColor)(THIS_ D3DCOLOR) PURE; + + STDMETHOD(GetDecalSize)(THIS_ D3DVALUE *width_return, D3DVALUE *height_return) PURE; + STDMETHOD(GetDecalOrigin)(THIS_ LONG *x_return, LONG *y_return) PURE; + + STDMETHOD_(D3DRMIMAGE *, GetImage)(THIS) PURE; + STDMETHOD_(DWORD, GetShades)(THIS) PURE; + STDMETHOD_(DWORD, GetColors)(THIS) PURE; + STDMETHOD_(DWORD, GetDecalScale)(THIS) PURE; + STDMETHOD_(BOOL, GetDecalTransparency)(THIS) PURE; + STDMETHOD_(D3DCOLOR, GetDecalTransparentColor)(THIS) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMWrap + +DECLARE_INTERFACE_(IDirect3DRMWrap, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMWrap methods + */ + STDMETHOD(Init) + ( THIS_ D3DRMWRAPTYPE, LPDIRECT3DRMFRAME ref, + D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, + D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, + D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, + D3DVALUE ou, D3DVALUE ov, + D3DVALUE su, D3DVALUE sv + ) PURE; + STDMETHOD(Apply)(THIS_ LPDIRECT3DRMOBJECT) PURE; + STDMETHOD(ApplyRelative)(THIS_ LPDIRECT3DRMFRAME frame, LPDIRECT3DRMOBJECT) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMMaterial + +DECLARE_INTERFACE_(IDirect3DRMMaterial, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMMaterial methods + */ + STDMETHOD(SetPower)(THIS_ D3DVALUE power) PURE; + STDMETHOD(SetSpecular)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE; + STDMETHOD(SetEmissive)(THIS_ D3DVALUE r, D3DVALUE g, D3DVALUE b) PURE; + + STDMETHOD_(D3DVALUE, GetPower)(THIS) PURE; + STDMETHOD(GetSpecular)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE; + STDMETHOD(GetEmissive)(THIS_ D3DVALUE* r, D3DVALUE* g, D3DVALUE* b) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMAnimation + +DECLARE_INTERFACE_(IDirect3DRMAnimation, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMAnimation methods + */ + STDMETHOD(SetOptions)(THIS_ D3DRMANIMATIONOPTIONS flags) PURE; + STDMETHOD(AddRotateKey)(THIS_ D3DVALUE time, D3DRMQUATERNION *q) PURE; + STDMETHOD(AddPositionKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(AddScaleKey)(THIS_ D3DVALUE time, D3DVALUE x, D3DVALUE y, D3DVALUE z) PURE; + STDMETHOD(DeleteKey)(THIS_ D3DVALUE time) PURE; + STDMETHOD(SetFrame)(THIS_ LPDIRECT3DRMFRAME frame) PURE; + STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE; + + STDMETHOD_(D3DRMANIMATIONOPTIONS, GetOptions)(THIS) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMAnimationSet + +DECLARE_INTERFACE_(IDirect3DRMAnimationSet, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMAnimationSet methods + */ + STDMETHOD(AddAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE; + STDMETHOD(Load)(THIS_ LPVOID filename, LPVOID name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURECALLBACK, LPVOID lpArg, LPDIRECT3DRMFRAME parent)PURE; + STDMETHOD(DeleteAnimation)(THIS_ LPDIRECT3DRMANIMATION aid) PURE; + STDMETHOD(SetTime)(THIS_ D3DVALUE time) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMUserVisual + +DECLARE_INTERFACE_(IDirect3DRMUserVisual, IDirect3DRMVisual) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMUserVisual methods + */ + STDMETHOD(Init)(THIS_ D3DRMUSERVISUALCALLBACK fn, void *arg) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMArray + +DECLARE_INTERFACE_(IDirect3DRMArray, IUnknown) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + /* No GetElement method as it would get overloaded + * in derived classes, and overloading is + * a no-no in COM + */ +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMDeviceArray + +DECLARE_INTERFACE_(IDirect3DRMDeviceArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMDEVICE *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMFrameArray + +DECLARE_INTERFACE_(IDirect3DRMFrameArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFRAME *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMViewportArray + +DECLARE_INTERFACE_(IDirect3DRMViewportArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVIEWPORT *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMVisualArray + +DECLARE_INTERFACE_(IDirect3DRMVisualArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMPickedArray + +DECLARE_INTERFACE_(IDirect3DRMPickedArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetPick)(THIS_ DWORD index, LPDIRECT3DRMVISUAL *, LPDIRECT3DRMFRAMEARRAY *, LPD3DRMPICKDESC) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMLightArray + +DECLARE_INTERFACE_(IDirect3DRMLightArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMLIGHT *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IDirect3DRMFaceArray + +DECLARE_INTERFACE_(IDirect3DRMFaceArray, IDirect3DRMArray) +{ + IUNKNOWN_METHODS(PURE); + + STDMETHOD_(DWORD, GetSize)(THIS) PURE; + STDMETHOD(GetElement)(THIS_ DWORD index, LPDIRECT3DRMFACE *) PURE; +}; + +#ifdef __cplusplus +}; +#endif +#endif /* _D3DRMOBJ_H_ */ diff --git a/WinQuake/dxsdk/SDK/INC/D3DRMWIN.H b/WinQuake/dxsdk/SDK/INC/D3DRMWIN.H index 6cda7e6..2c62bb3 100644 --- a/WinQuake/dxsdk/SDK/INC/D3DRMWIN.H +++ b/WinQuake/dxsdk/SDK/INC/D3DRMWIN.H @@ -1,48 +1,48 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3drm.h - * Content: Direct3DRM include file - * - ***************************************************************************/ - -#ifndef __D3DRMWIN_H__ -#define __D3DRMWIN_H__ - -#ifndef WIN32 -#define WIN32 -#endif - -#include "d3drm.h" -#include "ddraw.h" -#include "d3d.h" - -/* - * GUIDS used by Direct3DRM Windows interface - */ -DEFINE_GUID(IID_IDirect3DRMWinDevice, 0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); - -WIN_TYPES(IDirect3DRMWinDevice, DIRECT3DRMWINDEVICE); - -#undef INTERFACE -#define INTERFACE IDirect3DRMWinDevice - -DECLARE_INTERFACE_(IDirect3DRMWinDevice, IDirect3DRMObject) -{ - IUNKNOWN_METHODS(PURE); - IDIRECT3DRMOBJECT_METHODS(PURE); - - /* - * IDirect3DRMWinDevice methods - */ - - /* Repaint the window with the last frame which was rendered. */ - STDMETHOD(HandlePaint)(THIS_ HDC hdc) PURE; - - /* Respond to a WM_ACTIVATE message. */ - STDMETHOD(HandleActivate)(THIS_ WORD wparam) PURE; -}; - - -#endif +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3drm.h + * Content: Direct3DRM include file + * + ***************************************************************************/ + +#ifndef __D3DRMWIN_H__ +#define __D3DRMWIN_H__ + +#ifndef WIN32 +#define WIN32 +#endif + +#include "d3drm.h" +#include "ddraw.h" +#include "d3d.h" + +/* + * GUIDS used by Direct3DRM Windows interface + */ +DEFINE_GUID(IID_IDirect3DRMWinDevice, 0xc5016cc0, 0xd273, 0x11ce, 0xac, 0x48, 0x0, 0x0, 0xc0, 0x38, 0x25, 0xa1); + +WIN_TYPES(IDirect3DRMWinDevice, DIRECT3DRMWINDEVICE); + +#undef INTERFACE +#define INTERFACE IDirect3DRMWinDevice + +DECLARE_INTERFACE_(IDirect3DRMWinDevice, IDirect3DRMObject) +{ + IUNKNOWN_METHODS(PURE); + IDIRECT3DRMOBJECT_METHODS(PURE); + + /* + * IDirect3DRMWinDevice methods + */ + + /* Repaint the window with the last frame which was rendered. */ + STDMETHOD(HandlePaint)(THIS_ HDC hdc) PURE; + + /* Respond to a WM_ACTIVATE message. */ + STDMETHOD(HandleActivate)(THIS_ WORD wparam) PURE; +}; + + +#endif diff --git a/WinQuake/dxsdk/SDK/INC/D3DTYPES.H b/WinQuake/dxsdk/SDK/INC/D3DTYPES.H index 64343b7..66269aa 100644 --- a/WinQuake/dxsdk/SDK/INC/D3DTYPES.H +++ b/WinQuake/dxsdk/SDK/INC/D3DTYPES.H @@ -1,956 +1,956 @@ -/*==========================================================================; - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: d3dtypes.h - * Content: Direct3D types include file - * - ***************************************************************************/ - -#ifndef _D3DTYPES_H_ -#define _D3DTYPES_H_ - -#ifndef WIN32 -#include "subwtype.h" -#else -#include -#endif - -#include - -#pragma pack(4) - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* D3DVALUE is the fundamental Direct3D fractional data type */ - -#define D3DVALP(val, prec) ((float)(val)) -#define D3DVAL(val) ((float)(val)) -typedef float D3DVALUE, *LPD3DVALUE; -#define D3DDivide(a, b) (float)((double) (a) / (double) (b)) -#define D3DMultiply(a, b) ((a) * (b)) - -typedef LONG D3DFIXED; - -#ifndef RGB_MAKE -/* - * Format of CI colors is - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | alpha | color index | fraction | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define CI_GETALPHA(ci) ((ci) >> 24) -#define CI_GETINDEX(ci) (((ci) >> 8) & 0xffff) -#define CI_GETFRACTION(ci) ((ci) & 0xff) -#define CI_ROUNDINDEX(ci) CI_GETINDEX((ci) + 0x80) -#define CI_MASKALPHA(ci) ((ci) & 0xffffff) -#define CI_MAKE(a, i, f) (((a) << 24) | ((i) << 8) | (f)) - -/* - * Format of RGBA colors is - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | alpha | red | green | blue | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define RGBA_GETALPHA(rgb) ((rgb) >> 24) -#define RGBA_GETRED(rgb) (((rgb) >> 16) & 0xff) -#define RGBA_GETGREEN(rgb) (((rgb) >> 8) & 0xff) -#define RGBA_GETBLUE(rgb) ((rgb) & 0xff) -#define RGBA_MAKE(r, g, b, a) ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) - -/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs - * The float values must be in the range 0..1 - */ -#define D3DRGB(r, g, b) \ - (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255)) -#define D3DRGBA(r, g, b, a) \ - ( (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \ - | (((long)((g) * 255)) << 8) | (long)((b) * 255) \ - ) - -/* - * Format of RGB colors is - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ignored | red | green | blue | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define RGB_GETRED(rgb) (((rgb) >> 16) & 0xff) -#define RGB_GETGREEN(rgb) (((rgb) >> 8) & 0xff) -#define RGB_GETBLUE(rgb) ((rgb) & 0xff) -#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff)) -#define RGB_MAKE(r, g, b) ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b))) -#define RGBA_TORGB(rgba) ((D3DCOLOR) ((rgba) & 0xffffff)) -#define RGB_TORGBA(rgb) ((D3DCOLOR) ((rgb) | 0xff000000)) - -#endif - -/* - * Flags for Enumerate functions - */ - -/* - * Stop the enumeration - */ -#define D3DENUMRET_CANCEL DDENUMRET_CANCEL - -/* - * Continue the enumeration - */ -#define D3DENUMRET_OK DDENUMRET_OK - -typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset); -typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext); - -typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR; - -typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE; -typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE; -typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE; - -typedef struct _D3DCOLORVALUE { - union { - D3DVALUE r; - D3DVALUE dvR; - }; - union { - D3DVALUE g; - D3DVALUE dvG; - }; - union { - D3DVALUE b; - D3DVALUE dvB; - }; - union { - D3DVALUE a; - D3DVALUE dvA; - }; -} D3DCOLORVALUE; - -typedef struct _D3DRECT { - union { - LONG x1; - LONG lX1; - }; - union { - LONG y1; - LONG lY1; - }; - union { - LONG x2; - LONG lX2; - }; - union { - LONG y2; - LONG lY2; - }; -} D3DRECT, *LPD3DRECT; - -typedef struct _D3DVECTOR { - union { - D3DVALUE x; - D3DVALUE dvX; - }; - union { - D3DVALUE y; - D3DVALUE dvY; - }; - union { - D3DVALUE z; - D3DVALUE dvZ; - }; -} D3DVECTOR, *LPD3DVECTOR; - - -/* - * Vertex data types supported in an ExecuteBuffer. - */ - -/* - * Homogeneous vertices - */ - -typedef struct _D3DHVERTEX { - DWORD dwFlags; /* Homogeneous clipping flags */ - union { - D3DVALUE hx; - D3DVALUE dvHX; - }; - union { - D3DVALUE hy; - D3DVALUE dvHY; - }; - union { - D3DVALUE hz; - D3DVALUE dvHZ; - }; -} D3DHVERTEX, *LPD3DHVERTEX; - -/* - * Transformed/lit vertices - */ -typedef struct _D3DTLVERTEX { - union { - D3DVALUE sx; /* Screen coordinates */ - D3DVALUE dvSX; - }; - union { - D3DVALUE sy; - D3DVALUE dvSY; - }; - union { - D3DVALUE sz; - D3DVALUE dvSZ; - }; - union { - D3DVALUE rhw; /* Reciprocal of homogeneous w */ - D3DVALUE dvRHW; - }; - union { - D3DCOLOR color; /* Vertex color */ - D3DCOLOR dcColor; - }; - union { - D3DCOLOR specular; /* Specular component of vertex */ - D3DCOLOR dcSpecular; - }; - union { - D3DVALUE tu; /* Texture coordinates */ - D3DVALUE dvTU; - }; - union { - D3DVALUE tv; - D3DVALUE dvTV; - }; -} D3DTLVERTEX, *LPD3DTLVERTEX; - -/* - * Untransformed/lit vertices - */ -typedef struct _D3DLVERTEX { - union { - D3DVALUE x; /* Homogeneous coordinates */ - D3DVALUE dvX; - }; - union { - D3DVALUE y; - D3DVALUE dvY; - }; - union { - D3DVALUE z; - D3DVALUE dvZ; - }; - DWORD dwReserved; - union { - D3DCOLOR color; /* Vertex color */ - D3DCOLOR dcColor; - }; - union { - D3DCOLOR specular; /* Specular component of vertex */ - D3DCOLOR dcSpecular; - }; - union { - D3DVALUE tu; /* Texture coordinates */ - D3DVALUE dvTU; - }; - union { - D3DVALUE tv; - D3DVALUE dvTV; - }; -} D3DLVERTEX, *LPD3DLVERTEX; - -/* - * Untransformed/unlit vertices - */ - -typedef struct _D3DVERTEX { - union { - D3DVALUE x; /* Homogeneous coordinates */ - D3DVALUE dvX; - }; - union { - D3DVALUE y; - D3DVALUE dvY; - }; - union { - D3DVALUE z; - D3DVALUE dvZ; - }; - union { - D3DVALUE nx; /* Normal */ - D3DVALUE dvNX; - }; - union { - D3DVALUE ny; - D3DVALUE dvNY; - }; - union { - D3DVALUE nz; - D3DVALUE dvNZ; - }; - union { - D3DVALUE tu; /* Texture coordinates */ - D3DVALUE dvTU; - }; - union { - D3DVALUE tv; - D3DVALUE dvTV; - }; -} D3DVERTEX, *LPD3DVERTEX; - -/* - * Matrix, viewport, and tranformation structures and definitions. - */ - -typedef struct _D3DMATRIX { - D3DVALUE _11, _12, _13, _14; - D3DVALUE _21, _22, _23, _24; - D3DVALUE _31, _32, _33, _34; - D3DVALUE _41, _42, _43, _44; -} D3DMATRIX, *LPD3DMATRIX; - -typedef struct _D3DVIEWPORT { - DWORD dwSize; - DWORD dwX; - DWORD dwY; /* Top left */ - DWORD dwWidth; - DWORD dwHeight; /* Dimensions */ - D3DVALUE dvScaleX; /* Scale homogeneous to screen */ - D3DVALUE dvScaleY; /* Scale homogeneous to screen */ - D3DVALUE dvMaxX; /* Min/max homogeneous x coord */ - D3DVALUE dvMaxY; /* Min/max homogeneous y coord */ - D3DVALUE dvMinZ; - D3DVALUE dvMaxZ; /* Min/max homogeneous z coord */ -} D3DVIEWPORT, *LPD3DVIEWPORT; - -/* - * Values for clip fields. - */ -#define D3DCLIP_LEFT 0x00000001L -#define D3DCLIP_RIGHT 0x00000002L -#define D3DCLIP_TOP 0x00000004L -#define D3DCLIP_BOTTOM 0x00000008L -#define D3DCLIP_FRONT 0x00000010L -#define D3DCLIP_BACK 0x00000020L -#define D3DCLIP_GEN0 0x00000040L -#define D3DCLIP_GEN1 0x00000080L -#define D3DCLIP_GEN2 0x00000100L -#define D3DCLIP_GEN3 0x00000200L -#define D3DCLIP_GEN4 0x00000400L -#define D3DCLIP_GEN5 0x00000800L - -/* - * Values for d3d status. - */ -#define D3DSTATUS_CLIPUNIONLEFT D3DCLIP_LEFT -#define D3DSTATUS_CLIPUNIONRIGHT D3DCLIP_RIGHT -#define D3DSTATUS_CLIPUNIONTOP D3DCLIP_TOP -#define D3DSTATUS_CLIPUNIONBOTTOM D3DCLIP_BOTTOM -#define D3DSTATUS_CLIPUNIONFRONT D3DCLIP_FRONT -#define D3DSTATUS_CLIPUNIONBACK D3DCLIP_BACK -#define D3DSTATUS_CLIPUNIONGEN0 D3DCLIP_GEN0 -#define D3DSTATUS_CLIPUNIONGEN1 D3DCLIP_GEN1 -#define D3DSTATUS_CLIPUNIONGEN2 D3DCLIP_GEN2 -#define D3DSTATUS_CLIPUNIONGEN3 D3DCLIP_GEN3 -#define D3DSTATUS_CLIPUNIONGEN4 D3DCLIP_GEN4 -#define D3DSTATUS_CLIPUNIONGEN5 D3DCLIP_GEN5 - -#define D3DSTATUS_CLIPINTERSECTIONLEFT 0x00001000L -#define D3DSTATUS_CLIPINTERSECTIONRIGHT 0x00002000L -#define D3DSTATUS_CLIPINTERSECTIONTOP 0x00004000L -#define D3DSTATUS_CLIPINTERSECTIONBOTTOM 0x00008000L -#define D3DSTATUS_CLIPINTERSECTIONFRONT 0x00010000L -#define D3DSTATUS_CLIPINTERSECTIONBACK 0x00020000L -#define D3DSTATUS_CLIPINTERSECTIONGEN0 0x00040000L -#define D3DSTATUS_CLIPINTERSECTIONGEN1 0x00080000L -#define D3DSTATUS_CLIPINTERSECTIONGEN2 0x00100000L -#define D3DSTATUS_CLIPINTERSECTIONGEN3 0x00200000L -#define D3DSTATUS_CLIPINTERSECTIONGEN4 0x00400000L -#define D3DSTATUS_CLIPINTERSECTIONGEN5 0x00800000L -#define D3DSTATUS_ZNOTVISIBLE 0x01000000L - -#define D3DSTATUS_CLIPUNIONALL ( \ - D3DSTATUS_CLIPUNIONLEFT | \ - D3DSTATUS_CLIPUNIONRIGHT | \ - D3DSTATUS_CLIPUNIONTOP | \ - D3DSTATUS_CLIPUNIONBOTTOM | \ - D3DSTATUS_CLIPUNIONFRONT | \ - D3DSTATUS_CLIPUNIONBACK | \ - D3DSTATUS_CLIPUNIONGEN0 | \ - D3DSTATUS_CLIPUNIONGEN1 | \ - D3DSTATUS_CLIPUNIONGEN2 | \ - D3DSTATUS_CLIPUNIONGEN3 | \ - D3DSTATUS_CLIPUNIONGEN4 | \ - D3DSTATUS_CLIPUNIONGEN5 \ - ) - -#define D3DSTATUS_CLIPINTERSECTIONALL ( \ - D3DSTATUS_CLIPINTERSECTIONLEFT | \ - D3DSTATUS_CLIPINTERSECTIONRIGHT | \ - D3DSTATUS_CLIPINTERSECTIONTOP | \ - D3DSTATUS_CLIPINTERSECTIONBOTTOM | \ - D3DSTATUS_CLIPINTERSECTIONFRONT | \ - D3DSTATUS_CLIPINTERSECTIONBACK | \ - D3DSTATUS_CLIPINTERSECTIONGEN0 | \ - D3DSTATUS_CLIPINTERSECTIONGEN1 | \ - D3DSTATUS_CLIPINTERSECTIONGEN2 | \ - D3DSTATUS_CLIPINTERSECTIONGEN3 | \ - D3DSTATUS_CLIPINTERSECTIONGEN4 | \ - D3DSTATUS_CLIPINTERSECTIONGEN5 \ - ) - -#define D3DSTATUS_DEFAULT ( \ - D3DSTATUS_CLIPINTERSECTIONALL | \ - D3DSTATUS_ZNOTVISIBLE) - - -/* - * Options for direct transform calls - */ -#define D3DTRANSFORM_CLIPPED 0x00000001l -#define D3DTRANSFORM_UNCLIPPED 0x00000002l - -typedef struct _D3DTRANSFORMDATA { - DWORD dwSize; - LPVOID lpIn; /* Input vertices */ - DWORD dwInSize; /* Stride of input vertices */ - LPVOID lpOut; /* Output vertices */ - DWORD dwOutSize; /* Stride of output vertices */ - LPD3DHVERTEX lpHOut; /* Output homogeneous vertices */ - DWORD dwClip; /* Clipping hint */ - DWORD dwClipIntersection; - DWORD dwClipUnion; /* Union of all clip flags */ - D3DRECT drExtent; /* Extent of transformed vertices */ -} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA; - -/* - * Structure defining position and direction properties for lighting. - */ -typedef struct _D3DLIGHTINGELEMENT { - D3DVECTOR dvPosition; /* Lightable point in model space */ - D3DVECTOR dvNormal; /* Normalised unit vector */ -} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT; - -/* - * Structure defining material properties for lighting. - */ -typedef struct _D3DMATERIAL { - DWORD dwSize; - union { - D3DCOLORVALUE diffuse; /* Diffuse color RGBA */ - D3DCOLORVALUE dcvDiffuse; - }; - union { - D3DCOLORVALUE ambient; /* Ambient color RGB */ - D3DCOLORVALUE dcvAmbient; - }; - union { - D3DCOLORVALUE specular; /* Specular 'shininess' */ - D3DCOLORVALUE dcvSpecular; - }; - union { - D3DCOLORVALUE emissive; /* Emissive color RGB */ - D3DCOLORVALUE dcvEmissive; - }; - union { - D3DVALUE power; /* Sharpness if specular highlight */ - D3DVALUE dvPower; - }; - D3DTEXTUREHANDLE hTexture; /* Handle to texture map */ - DWORD dwRampSize; -} D3DMATERIAL, *LPD3DMATERIAL; - -typedef enum _D3DLIGHTTYPE { - D3DLIGHT_POINT = 1, - D3DLIGHT_SPOT = 2, - D3DLIGHT_DIRECTIONAL = 3, - D3DLIGHT_PARALLELPOINT = 4, - D3DLIGHT_GLSPOT = 5, -} D3DLIGHTTYPE; - -/* - * Structure defining a light source and its properties. - */ -typedef struct _D3DLIGHT { - DWORD dwSize; - D3DLIGHTTYPE dltType; /* Type of light source */ - D3DCOLORVALUE dcvColor; /* Color of light */ - D3DVECTOR dvPosition; /* Position in world space */ - D3DVECTOR dvDirection; /* Direction in world space */ - D3DVALUE dvRange; /* Cutoff range */ - D3DVALUE dvFalloff; /* Falloff */ - D3DVALUE dvAttenuation0; /* Constant attenuation */ - D3DVALUE dvAttenuation1; /* Linear attenuation */ - D3DVALUE dvAttenuation2; /* Quadratic attenuation */ - D3DVALUE dvTheta; /* Inner angle of spotlight cone */ - D3DVALUE dvPhi; /* Outer angle of spotlight cone */ -} D3DLIGHT, *LPD3DLIGHT; - -typedef struct _D3DLIGHTDATA { - DWORD dwSize; - LPD3DLIGHTINGELEMENT lpIn; /* Input positions and normals */ - DWORD dwInSize; /* Stride of input elements */ - LPD3DTLVERTEX lpOut; /* Output colors */ - DWORD dwOutSize; /* Stride of output colors */ -} D3DLIGHTDATA, *LPD3DLIGHTDATA; - -typedef enum _D3DCOLORMODEL { - D3DCOLOR_MONO = 1, - D3DCOLOR_RGB = 2, -} D3DCOLORMODEL; - -/* - * Options for clearing - */ -#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ -#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ - -/* - * Execute buffers are allocated via Direct3D. These buffers may then - * be filled by the application with instructions to execute along with - * vertex data. - */ - -/* - * Supported op codes for execute instructions. - */ -typedef enum _D3DOPCODE { - D3DOP_POINT = 1, - D3DOP_LINE = 2, - D3DOP_TRIANGLE = 3, - D3DOP_MATRIXLOAD = 4, - D3DOP_MATRIXMULTIPLY = 5, - D3DOP_STATETRANSFORM = 6, - D3DOP_STATELIGHT = 7, - D3DOP_STATERENDER = 8, - D3DOP_PROCESSVERTICES = 9, - D3DOP_TEXTURELOAD = 10, - D3DOP_EXIT = 11, - D3DOP_BRANCHFORWARD = 12, - D3DOP_SPAN = 13, - D3DOP_SETSTATUS = 14, -} D3DOPCODE; - -typedef struct _D3DINSTRUCTION { - BYTE bOpcode; /* Instruction opcode */ - BYTE bSize; /* Size of each instruction data unit */ - WORD wCount; /* Count of instruction data units to follow */ -} D3DINSTRUCTION, *LPD3DINSTRUCTION; - -/* - * Structure for texture loads - */ -typedef struct _D3DTEXTURELOAD { - D3DTEXTUREHANDLE hDestTexture; - D3DTEXTUREHANDLE hSrcTexture; -} D3DTEXTURELOAD, *LPD3DTEXTURELOAD; - -/* - * Structure for picking - */ -typedef struct _D3DPICKRECORD { - BYTE bOpcode; - BYTE bPad; - DWORD dwOffset; - D3DVALUE dvZ; -} D3DPICKRECORD, *LPD3DPICKRECORD; - -/* - * The following defines the rendering states which can be set in the - * execute buffer. - */ - -typedef enum _D3DSHADEMODE { - D3DSHADE_FLAT = 1, - D3DSHADE_GOURAUD = 2, - D3DSHADE_PHONG = 3, -} D3DSHADEMODE; - -typedef enum _D3DFILLMODE { - D3DFILL_POINT = 1, - D3DFILL_WIREFRAME = 2, - D3DFILL_SOLID = 3, -} D3DFILLMODE; - -typedef struct _D3DLINEPATTERN { - WORD wRepeatFactor; - WORD wLinePattern; -} D3DLINEPATTERN; - -typedef enum _D3DTEXTUREFILTER { - D3DFILTER_NEAREST = 1, - D3DFILTER_LINEAR = 2, - D3DFILTER_MIPNEAREST = 3, - D3DFILTER_MIPLINEAR = 4, - D3DFILTER_LINEARMIPNEAREST = 5, - D3DFILTER_LINEARMIPLINEAR = 6, -} D3DTEXTUREFILTER; - -typedef enum _D3DBLEND { - D3DBLEND_ZERO = 1, - D3DBLEND_ONE = 2, - D3DBLEND_SRCCOLOR = 3, - D3DBLEND_INVSRCCOLOR = 4, - D3DBLEND_SRCALPHA = 5, - D3DBLEND_INVSRCALPHA = 6, - D3DBLEND_DESTALPHA = 7, - D3DBLEND_INVDESTALPHA = 8, - D3DBLEND_DESTCOLOR = 9, - D3DBLEND_INVDESTCOLOR = 10, - D3DBLEND_SRCALPHASAT = 11, - D3DBLEND_BOTHSRCALPHA = 12, - D3DBLEND_BOTHINVSRCALPHA = 13, -} D3DBLEND; - -typedef enum _D3DTEXTUREBLEND { - D3DTBLEND_DECAL = 1, - D3DTBLEND_MODULATE = 2, - D3DTBLEND_DECALALPHA = 3, - D3DTBLEND_MODULATEALPHA = 4, - D3DTBLEND_DECALMASK = 5, - D3DTBLEND_MODULATEMASK = 6, - D3DTBLEND_COPY = 7, -} D3DTEXTUREBLEND; - -typedef enum _D3DTEXTUREADDRESS { - D3DTADDRESS_WRAP = 1, - D3DTADDRESS_MIRROR = 2, - D3DTADDRESS_CLAMP = 3, -} D3DTEXTUREADDRESS; - -typedef enum _D3DCULL { - D3DCULL_NONE = 1, - D3DCULL_CW = 2, - D3DCULL_CCW = 3, -} D3DCULL; - -typedef enum _D3DCMPFUNC { - D3DCMP_NEVER = 1, - D3DCMP_LESS = 2, - D3DCMP_EQUAL = 3, - D3DCMP_LESSEQUAL = 4, - D3DCMP_GREATER = 5, - D3DCMP_NOTEQUAL = 6, - D3DCMP_GREATEREQUAL = 7, - D3DCMP_ALWAYS = 8, -} D3DCMPFUNC; - -typedef enum _D3DFOGMODE { - D3DFOG_NONE = 0, - D3DFOG_EXP = 1, - D3DFOG_EXP2 = 2, - D3DFOG_LINEAR = 3 -} D3DFOGMODE; - -/* - * Amount to add to a state to generate the override for that state. - */ -#define D3DSTATE_OVERRIDE_BIAS 256 - -/* - * A state which sets the override flag for the specified state type. - */ -#define D3DSTATE_OVERRIDE(type) ((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS) - -typedef enum _D3DTRANSFORMSTATETYPE { - D3DTRANSFORMSTATE_WORLD = 1, - D3DTRANSFORMSTATE_VIEW = 2, - D3DTRANSFORMSTATE_PROJECTION = 3, -} D3DTRANSFORMSTATETYPE; - -typedef enum _D3DLIGHTSTATETYPE { - D3DLIGHTSTATE_MATERIAL = 1, - D3DLIGHTSTATE_AMBIENT = 2, - D3DLIGHTSTATE_COLORMODEL = 3, - D3DLIGHTSTATE_FOGMODE = 4, - D3DLIGHTSTATE_FOGSTART = 5, - D3DLIGHTSTATE_FOGEND = 6, - D3DLIGHTSTATE_FOGDENSITY = 7, -} D3DLIGHTSTATETYPE; - -typedef enum _D3DRENDERSTATETYPE { - D3DRENDERSTATE_TEXTUREHANDLE = 1, /* Texture handle */ - D3DRENDERSTATE_ANTIALIAS = 2, /* Antialiasing prim edges */ - D3DRENDERSTATE_TEXTUREADDRESS = 3, /* D3DTEXTUREADDRESS */ - D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4, /* TRUE for perspective correction */ - D3DRENDERSTATE_WRAPU = 5, /* TRUE for wrapping in u */ - D3DRENDERSTATE_WRAPV = 6, /* TRUE for wrapping in v */ - D3DRENDERSTATE_ZENABLE = 7, /* TRUE to enable z test */ - D3DRENDERSTATE_FILLMODE = 8, /* D3DFILL_MODE */ - D3DRENDERSTATE_SHADEMODE = 9, /* D3DSHADEMODE */ - D3DRENDERSTATE_LINEPATTERN = 10, /* D3DLINEPATTERN */ - D3DRENDERSTATE_MONOENABLE = 11, /* TRUE to enable mono rasterization */ - D3DRENDERSTATE_ROP2 = 12, /* ROP2 */ - D3DRENDERSTATE_PLANEMASK = 13, /* DWORD physical plane mask */ - D3DRENDERSTATE_ZWRITEENABLE = 14, /* TRUE to enable z writes */ - D3DRENDERSTATE_ALPHATESTENABLE = 15, /* TRUE to enable alpha tests */ - D3DRENDERSTATE_LASTPIXEL = 16, /* TRUE for last-pixel on lines */ - D3DRENDERSTATE_TEXTUREMAG = 17, /* D3DTEXTUREFILTER */ - D3DRENDERSTATE_TEXTUREMIN = 18, /* D3DTEXTUREFILTER */ - D3DRENDERSTATE_SRCBLEND = 19, /* D3DBLEND */ - D3DRENDERSTATE_DESTBLEND = 20, /* D3DBLEND */ - D3DRENDERSTATE_TEXTUREMAPBLEND = 21, /* D3DTEXTUREBLEND */ - D3DRENDERSTATE_CULLMODE = 22, /* D3DCULL */ - D3DRENDERSTATE_ZFUNC = 23, /* D3DCMPFUNC */ - D3DRENDERSTATE_ALPHAREF = 24, /* D3DFIXED */ - D3DRENDERSTATE_ALPHAFUNC = 25, /* D3DCMPFUNC */ - D3DRENDERSTATE_DITHERENABLE = 26, /* TRUE to enable dithering */ - D3DRENDERSTATE_BLENDENABLE = 27, /* TRUE to enable alpha blending */ - D3DRENDERSTATE_FOGENABLE = 28, /* TRUE to enable fog */ - D3DRENDERSTATE_SPECULARENABLE = 29, /* TRUE to enable specular */ - D3DRENDERSTATE_ZVISIBLE = 30, /* TRUE to enable z checking */ - D3DRENDERSTATE_SUBPIXEL = 31, /* TRUE to enable subpixel correction */ - D3DRENDERSTATE_SUBPIXELX = 32, /* TRUE to enable correction in X only */ - D3DRENDERSTATE_STIPPLEDALPHA = 33, /* TRUE to enable stippled alpha */ - D3DRENDERSTATE_FOGCOLOR = 34, /* D3DCOLOR */ - D3DRENDERSTATE_FOGTABLEMODE = 35, /* D3DFOGMODE */ - D3DRENDERSTATE_FOGTABLESTART = 36, /* Fog table start */ - D3DRENDERSTATE_FOGTABLEEND = 37, /* Fog table end */ - D3DRENDERSTATE_FOGTABLEDENSITY = 38, /* Fog table density */ - D3DRENDERSTATE_STIPPLEENABLE = 39, /* TRUE to enable stippling */ - D3DRENDERSTATE_STIPPLEPATTERN00 = 64, /* Stipple pattern 01... */ - D3DRENDERSTATE_STIPPLEPATTERN01 = 65, - D3DRENDERSTATE_STIPPLEPATTERN02 = 66, - D3DRENDERSTATE_STIPPLEPATTERN03 = 67, - D3DRENDERSTATE_STIPPLEPATTERN04 = 68, - D3DRENDERSTATE_STIPPLEPATTERN05 = 69, - D3DRENDERSTATE_STIPPLEPATTERN06 = 70, - D3DRENDERSTATE_STIPPLEPATTERN07 = 71, - D3DRENDERSTATE_STIPPLEPATTERN08 = 72, - D3DRENDERSTATE_STIPPLEPATTERN09 = 73, - D3DRENDERSTATE_STIPPLEPATTERN10 = 74, - D3DRENDERSTATE_STIPPLEPATTERN11 = 75, - D3DRENDERSTATE_STIPPLEPATTERN12 = 76, - D3DRENDERSTATE_STIPPLEPATTERN13 = 77, - D3DRENDERSTATE_STIPPLEPATTERN14 = 78, - D3DRENDERSTATE_STIPPLEPATTERN15 = 79, - D3DRENDERSTATE_STIPPLEPATTERN16 = 80, - D3DRENDERSTATE_STIPPLEPATTERN17 = 81, - D3DRENDERSTATE_STIPPLEPATTERN18 = 82, - D3DRENDERSTATE_STIPPLEPATTERN19 = 83, - D3DRENDERSTATE_STIPPLEPATTERN20 = 84, - D3DRENDERSTATE_STIPPLEPATTERN21 = 85, - D3DRENDERSTATE_STIPPLEPATTERN22 = 86, - D3DRENDERSTATE_STIPPLEPATTERN23 = 87, - D3DRENDERSTATE_STIPPLEPATTERN24 = 88, - D3DRENDERSTATE_STIPPLEPATTERN25 = 89, - D3DRENDERSTATE_STIPPLEPATTERN26 = 90, - D3DRENDERSTATE_STIPPLEPATTERN27 = 91, - D3DRENDERSTATE_STIPPLEPATTERN28 = 92, - D3DRENDERSTATE_STIPPLEPATTERN29 = 93, - D3DRENDERSTATE_STIPPLEPATTERN30 = 94, - D3DRENDERSTATE_STIPPLEPATTERN31 = 95, -} D3DRENDERSTATETYPE; - -#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y)) - -typedef struct _D3DSTATE { - union { - D3DTRANSFORMSTATETYPE dtstTransformStateType; - D3DLIGHTSTATETYPE dlstLightStateType; - D3DRENDERSTATETYPE drstRenderStateType; - }; - union { - DWORD dwArg[1]; - D3DVALUE dvArg[1]; - }; -} D3DSTATE, *LPD3DSTATE; - -/* - * Operation used to load matrices - * hDstMat = hSrcMat - */ -typedef struct _D3DMATRIXLOAD { - D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ - D3DMATRIXHANDLE hSrcMatrix; /* Source matrix */ -} D3DMATRIXLOAD, *LPD3DMATRIXLOAD; - -/* - * Operation used to multiply matrices - * hDstMat = hSrcMat1 * hSrcMat2 - */ -typedef struct _D3DMATRIXMULTIPLY { - D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ - D3DMATRIXHANDLE hSrcMatrix1; /* First source matrix */ - D3DMATRIXHANDLE hSrcMatrix2; /* Second source matrix */ -} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY; - -/* - * Operation used to transform and light vertices. - */ -typedef struct _D3DPROCESSVERTICES { - DWORD dwFlags; /* Do we transform or light or just copy? */ - WORD wStart; /* Index to first vertex in source */ - WORD wDest; /* Index to first vertex in local buffer */ - DWORD dwCount; /* Number of vertices to be processed */ - DWORD dwReserved; /* Must be zero */ -} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES; - -#define D3DPROCESSVERTICES_TRANSFORMLIGHT 0x00000000L -#define D3DPROCESSVERTICES_TRANSFORM 0x00000001L -#define D3DPROCESSVERTICES_COPY 0x00000002L -#define D3DPROCESSVERTICES_OPMASK 0x00000007L - -#define D3DPROCESSVERTICES_UPDATEEXTENTS 0x00000008L -#define D3DPROCESSVERTICES_NOCOLOR 0x00000010L - - -/* - * Triangle flags - */ - -/* - * Tri strip and fan flags. - * START loads all three vertices - * EVEN and ODD load just v3 with even or odd culling - * START_FLAT contains a count from 0 to 29 that allows the - * whole strip or fan to be culled in one hit. - * e.g. for a quad len = 1 - */ -#define D3DTRIFLAG_START 0x00000000L -#define D3DTRIFLAG_STARTFLAT(len) (len) /* 0 < len < 30 */ -#define D3DTRIFLAG_ODD 0x0000001eL -#define D3DTRIFLAG_EVEN 0x0000001fL - -/* - * Triangle edge flags - * enable edges for wireframe or antialiasing - */ -#define D3DTRIFLAG_EDGEENABLE1 0x00000100L /* v0-v1 edge */ -#define D3DTRIFLAG_EDGEENABLE2 0x00000200L /* v1-v2 edge */ -#define D3DTRIFLAG_EDGEENABLE3 0x00000400L /* v2-v0 edge */ -#define D3DTRIFLAG_EDGEENABLETRIANGLE \ - (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3) - -/* - * Primitive structures and related defines. Vertex offsets are to types - * D3DVERTEX, D3DLVERTEX, or D3DTLVERTEX. - */ - -/* - * Triangle list primitive structure - */ -typedef struct _D3DTRIANGLE { - union { - WORD v1; /* Vertex indices */ - WORD wV1; - }; - union { - WORD v2; - WORD wV2; - }; - union { - WORD v3; - WORD wV3; - }; - WORD wFlags; /* Edge (and other) flags */ -} D3DTRIANGLE, *LPD3DTRIANGLE; - -/* - * Line strip structure. - * The instruction count - 1 defines the number of line segments. - */ -typedef struct _D3DLINE { - union { - WORD v1; /* Vertex indices */ - WORD wV1; - }; - union { - WORD v2; - WORD wV2; - }; -} D3DLINE, *LPD3DLINE; - -/* - * Span structure - * Spans join a list of points with the same y value. - * If the y value changes, a new span is started. - */ -typedef struct _D3DSPAN { - WORD wCount; /* Number of spans */ - WORD wFirst; /* Index to first vertex */ -} D3DSPAN, *LPD3DSPAN; - -/* - * Point structure - */ -typedef struct _D3DPOINT { - WORD wCount; /* number of points */ - WORD wFirst; /* index to first vertex */ -} D3DPOINT, *LPD3DPOINT; - - -/* - * Forward branch structure. - * Mask is logically anded with the driver status mask - * if the result equals 'value', the branch is taken. - */ -typedef struct _D3DBRANCH { - DWORD dwMask; /* Bitmask against D3D status */ - DWORD dwValue; - BOOL bNegate; /* TRUE to negate comparison */ - DWORD dwOffset; /* How far to branch forward (0 for exit)*/ -} D3DBRANCH, *LPD3DBRANCH; - -/* - * Status used for set status instruction. - * The D3D status is initialised on device creation - * and is modified by all execute calls. - */ -typedef struct _D3DSTATUS { - DWORD dwFlags; /* Do we set extents or status */ - DWORD dwStatus; /* D3D status */ - D3DRECT drExtent; -} D3DSTATUS, *LPD3DSTATUS; - -#define D3DSETSTATUS_STATUS 0x00000001L -#define D3DSETSTATUS_EXTENTS 0x00000002L -#define D3DSETSTATUS_ALL (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS) - -/* - * Statistics structure - */ -typedef struct _D3DSTATS { - DWORD dwSize; - DWORD dwTrianglesDrawn; - DWORD dwLinesDrawn; - DWORD dwPointsDrawn; - DWORD dwSpansDrawn; - DWORD dwVerticesProcessed; -} D3DSTATS, *LPD3DSTATS; - -/* - * Execute options. - * When calling using D3DEXECUTE_UNCLIPPED all the primitives - * inside the buffer must be contained within the viewport. - */ -#define D3DEXECUTE_CLIPPED 0x00000001l -#define D3DEXECUTE_UNCLIPPED 0x00000002l - -typedef struct _D3DEXECUTEDATA { - DWORD dwSize; - DWORD dwVertexOffset; - DWORD dwVertexCount; - DWORD dwInstructionOffset; - DWORD dwInstructionLength; - DWORD dwHVertexOffset; - D3DSTATUS dsStatus; /* Status after execute */ -} D3DEXECUTEDATA, *LPD3DEXECUTEDATA; - -/* - * Palette flags. - * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw. - */ -#define D3DPAL_FREE 0x00 /* Renderer may use this entry freely */ -#define D3DPAL_READONLY 0x40 /* Renderer may not set this entry */ -#define D3DPAL_RESERVED 0x80 /* Renderer may not use this entry */ - -#if defined(__cplusplus) -}; -#endif - -#pragma pack() - -#endif /* _D3DTYPES_H_ */ +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3dtypes.h + * Content: Direct3D types include file + * + ***************************************************************************/ + +#ifndef _D3DTYPES_H_ +#define _D3DTYPES_H_ + +#ifndef WIN32 +#include "subwtype.h" +#else +#include +#endif + +#include + +#pragma pack(4) + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* D3DVALUE is the fundamental Direct3D fractional data type */ + +#define D3DVALP(val, prec) ((float)(val)) +#define D3DVAL(val) ((float)(val)) +typedef float D3DVALUE, *LPD3DVALUE; +#define D3DDivide(a, b) (float)((double) (a) / (double) (b)) +#define D3DMultiply(a, b) ((a) * (b)) + +typedef LONG D3DFIXED; + +#ifndef RGB_MAKE +/* + * Format of CI colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | alpha | color index | fraction | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define CI_GETALPHA(ci) ((ci) >> 24) +#define CI_GETINDEX(ci) (((ci) >> 8) & 0xffff) +#define CI_GETFRACTION(ci) ((ci) & 0xff) +#define CI_ROUNDINDEX(ci) CI_GETINDEX((ci) + 0x80) +#define CI_MASKALPHA(ci) ((ci) & 0xffffff) +#define CI_MAKE(a, i, f) (((a) << 24) | ((i) << 8) | (f)) + +/* + * Format of RGBA colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | alpha | red | green | blue | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define RGBA_GETALPHA(rgb) ((rgb) >> 24) +#define RGBA_GETRED(rgb) (((rgb) >> 16) & 0xff) +#define RGBA_GETGREEN(rgb) (((rgb) >> 8) & 0xff) +#define RGBA_GETBLUE(rgb) ((rgb) & 0xff) +#define RGBA_MAKE(r, g, b, a) ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) + +/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs + * The float values must be in the range 0..1 + */ +#define D3DRGB(r, g, b) \ + (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255)) +#define D3DRGBA(r, g, b, a) \ + ( (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \ + | (((long)((g) * 255)) << 8) | (long)((b) * 255) \ + ) + +/* + * Format of RGB colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ignored | red | green | blue | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define RGB_GETRED(rgb) (((rgb) >> 16) & 0xff) +#define RGB_GETGREEN(rgb) (((rgb) >> 8) & 0xff) +#define RGB_GETBLUE(rgb) ((rgb) & 0xff) +#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff)) +#define RGB_MAKE(r, g, b) ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b))) +#define RGBA_TORGB(rgba) ((D3DCOLOR) ((rgba) & 0xffffff)) +#define RGB_TORGBA(rgb) ((D3DCOLOR) ((rgb) | 0xff000000)) + +#endif + +/* + * Flags for Enumerate functions + */ + +/* + * Stop the enumeration + */ +#define D3DENUMRET_CANCEL DDENUMRET_CANCEL + +/* + * Continue the enumeration + */ +#define D3DENUMRET_OK DDENUMRET_OK + +typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset); +typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext); + +typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR; + +typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE; +typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE; +typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE; + +typedef struct _D3DCOLORVALUE { + union { + D3DVALUE r; + D3DVALUE dvR; + }; + union { + D3DVALUE g; + D3DVALUE dvG; + }; + union { + D3DVALUE b; + D3DVALUE dvB; + }; + union { + D3DVALUE a; + D3DVALUE dvA; + }; +} D3DCOLORVALUE; + +typedef struct _D3DRECT { + union { + LONG x1; + LONG lX1; + }; + union { + LONG y1; + LONG lY1; + }; + union { + LONG x2; + LONG lX2; + }; + union { + LONG y2; + LONG lY2; + }; +} D3DRECT, *LPD3DRECT; + +typedef struct _D3DVECTOR { + union { + D3DVALUE x; + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; +} D3DVECTOR, *LPD3DVECTOR; + + +/* + * Vertex data types supported in an ExecuteBuffer. + */ + +/* + * Homogeneous vertices + */ + +typedef struct _D3DHVERTEX { + DWORD dwFlags; /* Homogeneous clipping flags */ + union { + D3DVALUE hx; + D3DVALUE dvHX; + }; + union { + D3DVALUE hy; + D3DVALUE dvHY; + }; + union { + D3DVALUE hz; + D3DVALUE dvHZ; + }; +} D3DHVERTEX, *LPD3DHVERTEX; + +/* + * Transformed/lit vertices + */ +typedef struct _D3DTLVERTEX { + union { + D3DVALUE sx; /* Screen coordinates */ + D3DVALUE dvSX; + }; + union { + D3DVALUE sy; + D3DVALUE dvSY; + }; + union { + D3DVALUE sz; + D3DVALUE dvSZ; + }; + union { + D3DVALUE rhw; /* Reciprocal of homogeneous w */ + D3DVALUE dvRHW; + }; + union { + D3DCOLOR color; /* Vertex color */ + D3DCOLOR dcColor; + }; + union { + D3DCOLOR specular; /* Specular component of vertex */ + D3DCOLOR dcSpecular; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DTLVERTEX, *LPD3DTLVERTEX; + +/* + * Untransformed/lit vertices + */ +typedef struct _D3DLVERTEX { + union { + D3DVALUE x; /* Homogeneous coordinates */ + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; + DWORD dwReserved; + union { + D3DCOLOR color; /* Vertex color */ + D3DCOLOR dcColor; + }; + union { + D3DCOLOR specular; /* Specular component of vertex */ + D3DCOLOR dcSpecular; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DLVERTEX, *LPD3DLVERTEX; + +/* + * Untransformed/unlit vertices + */ + +typedef struct _D3DVERTEX { + union { + D3DVALUE x; /* Homogeneous coordinates */ + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; + union { + D3DVALUE nx; /* Normal */ + D3DVALUE dvNX; + }; + union { + D3DVALUE ny; + D3DVALUE dvNY; + }; + union { + D3DVALUE nz; + D3DVALUE dvNZ; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DVERTEX, *LPD3DVERTEX; + +/* + * Matrix, viewport, and tranformation structures and definitions. + */ + +typedef struct _D3DMATRIX { + D3DVALUE _11, _12, _13, _14; + D3DVALUE _21, _22, _23, _24; + D3DVALUE _31, _32, _33, _34; + D3DVALUE _41, _42, _43, _44; +} D3DMATRIX, *LPD3DMATRIX; + +typedef struct _D3DVIEWPORT { + DWORD dwSize; + DWORD dwX; + DWORD dwY; /* Top left */ + DWORD dwWidth; + DWORD dwHeight; /* Dimensions */ + D3DVALUE dvScaleX; /* Scale homogeneous to screen */ + D3DVALUE dvScaleY; /* Scale homogeneous to screen */ + D3DVALUE dvMaxX; /* Min/max homogeneous x coord */ + D3DVALUE dvMaxY; /* Min/max homogeneous y coord */ + D3DVALUE dvMinZ; + D3DVALUE dvMaxZ; /* Min/max homogeneous z coord */ +} D3DVIEWPORT, *LPD3DVIEWPORT; + +/* + * Values for clip fields. + */ +#define D3DCLIP_LEFT 0x00000001L +#define D3DCLIP_RIGHT 0x00000002L +#define D3DCLIP_TOP 0x00000004L +#define D3DCLIP_BOTTOM 0x00000008L +#define D3DCLIP_FRONT 0x00000010L +#define D3DCLIP_BACK 0x00000020L +#define D3DCLIP_GEN0 0x00000040L +#define D3DCLIP_GEN1 0x00000080L +#define D3DCLIP_GEN2 0x00000100L +#define D3DCLIP_GEN3 0x00000200L +#define D3DCLIP_GEN4 0x00000400L +#define D3DCLIP_GEN5 0x00000800L + +/* + * Values for d3d status. + */ +#define D3DSTATUS_CLIPUNIONLEFT D3DCLIP_LEFT +#define D3DSTATUS_CLIPUNIONRIGHT D3DCLIP_RIGHT +#define D3DSTATUS_CLIPUNIONTOP D3DCLIP_TOP +#define D3DSTATUS_CLIPUNIONBOTTOM D3DCLIP_BOTTOM +#define D3DSTATUS_CLIPUNIONFRONT D3DCLIP_FRONT +#define D3DSTATUS_CLIPUNIONBACK D3DCLIP_BACK +#define D3DSTATUS_CLIPUNIONGEN0 D3DCLIP_GEN0 +#define D3DSTATUS_CLIPUNIONGEN1 D3DCLIP_GEN1 +#define D3DSTATUS_CLIPUNIONGEN2 D3DCLIP_GEN2 +#define D3DSTATUS_CLIPUNIONGEN3 D3DCLIP_GEN3 +#define D3DSTATUS_CLIPUNIONGEN4 D3DCLIP_GEN4 +#define D3DSTATUS_CLIPUNIONGEN5 D3DCLIP_GEN5 + +#define D3DSTATUS_CLIPINTERSECTIONLEFT 0x00001000L +#define D3DSTATUS_CLIPINTERSECTIONRIGHT 0x00002000L +#define D3DSTATUS_CLIPINTERSECTIONTOP 0x00004000L +#define D3DSTATUS_CLIPINTERSECTIONBOTTOM 0x00008000L +#define D3DSTATUS_CLIPINTERSECTIONFRONT 0x00010000L +#define D3DSTATUS_CLIPINTERSECTIONBACK 0x00020000L +#define D3DSTATUS_CLIPINTERSECTIONGEN0 0x00040000L +#define D3DSTATUS_CLIPINTERSECTIONGEN1 0x00080000L +#define D3DSTATUS_CLIPINTERSECTIONGEN2 0x00100000L +#define D3DSTATUS_CLIPINTERSECTIONGEN3 0x00200000L +#define D3DSTATUS_CLIPINTERSECTIONGEN4 0x00400000L +#define D3DSTATUS_CLIPINTERSECTIONGEN5 0x00800000L +#define D3DSTATUS_ZNOTVISIBLE 0x01000000L + +#define D3DSTATUS_CLIPUNIONALL ( \ + D3DSTATUS_CLIPUNIONLEFT | \ + D3DSTATUS_CLIPUNIONRIGHT | \ + D3DSTATUS_CLIPUNIONTOP | \ + D3DSTATUS_CLIPUNIONBOTTOM | \ + D3DSTATUS_CLIPUNIONFRONT | \ + D3DSTATUS_CLIPUNIONBACK | \ + D3DSTATUS_CLIPUNIONGEN0 | \ + D3DSTATUS_CLIPUNIONGEN1 | \ + D3DSTATUS_CLIPUNIONGEN2 | \ + D3DSTATUS_CLIPUNIONGEN3 | \ + D3DSTATUS_CLIPUNIONGEN4 | \ + D3DSTATUS_CLIPUNIONGEN5 \ + ) + +#define D3DSTATUS_CLIPINTERSECTIONALL ( \ + D3DSTATUS_CLIPINTERSECTIONLEFT | \ + D3DSTATUS_CLIPINTERSECTIONRIGHT | \ + D3DSTATUS_CLIPINTERSECTIONTOP | \ + D3DSTATUS_CLIPINTERSECTIONBOTTOM | \ + D3DSTATUS_CLIPINTERSECTIONFRONT | \ + D3DSTATUS_CLIPINTERSECTIONBACK | \ + D3DSTATUS_CLIPINTERSECTIONGEN0 | \ + D3DSTATUS_CLIPINTERSECTIONGEN1 | \ + D3DSTATUS_CLIPINTERSECTIONGEN2 | \ + D3DSTATUS_CLIPINTERSECTIONGEN3 | \ + D3DSTATUS_CLIPINTERSECTIONGEN4 | \ + D3DSTATUS_CLIPINTERSECTIONGEN5 \ + ) + +#define D3DSTATUS_DEFAULT ( \ + D3DSTATUS_CLIPINTERSECTIONALL | \ + D3DSTATUS_ZNOTVISIBLE) + + +/* + * Options for direct transform calls + */ +#define D3DTRANSFORM_CLIPPED 0x00000001l +#define D3DTRANSFORM_UNCLIPPED 0x00000002l + +typedef struct _D3DTRANSFORMDATA { + DWORD dwSize; + LPVOID lpIn; /* Input vertices */ + DWORD dwInSize; /* Stride of input vertices */ + LPVOID lpOut; /* Output vertices */ + DWORD dwOutSize; /* Stride of output vertices */ + LPD3DHVERTEX lpHOut; /* Output homogeneous vertices */ + DWORD dwClip; /* Clipping hint */ + DWORD dwClipIntersection; + DWORD dwClipUnion; /* Union of all clip flags */ + D3DRECT drExtent; /* Extent of transformed vertices */ +} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA; + +/* + * Structure defining position and direction properties for lighting. + */ +typedef struct _D3DLIGHTINGELEMENT { + D3DVECTOR dvPosition; /* Lightable point in model space */ + D3DVECTOR dvNormal; /* Normalised unit vector */ +} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT; + +/* + * Structure defining material properties for lighting. + */ +typedef struct _D3DMATERIAL { + DWORD dwSize; + union { + D3DCOLORVALUE diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE dcvDiffuse; + }; + union { + D3DCOLORVALUE ambient; /* Ambient color RGB */ + D3DCOLORVALUE dcvAmbient; + }; + union { + D3DCOLORVALUE specular; /* Specular 'shininess' */ + D3DCOLORVALUE dcvSpecular; + }; + union { + D3DCOLORVALUE emissive; /* Emissive color RGB */ + D3DCOLORVALUE dcvEmissive; + }; + union { + D3DVALUE power; /* Sharpness if specular highlight */ + D3DVALUE dvPower; + }; + D3DTEXTUREHANDLE hTexture; /* Handle to texture map */ + DWORD dwRampSize; +} D3DMATERIAL, *LPD3DMATERIAL; + +typedef enum _D3DLIGHTTYPE { + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_PARALLELPOINT = 4, + D3DLIGHT_GLSPOT = 5, +} D3DLIGHTTYPE; + +/* + * Structure defining a light source and its properties. + */ +typedef struct _D3DLIGHT { + DWORD dwSize; + D3DLIGHTTYPE dltType; /* Type of light source */ + D3DCOLORVALUE dcvColor; /* Color of light */ + D3DVECTOR dvPosition; /* Position in world space */ + D3DVECTOR dvDirection; /* Direction in world space */ + D3DVALUE dvRange; /* Cutoff range */ + D3DVALUE dvFalloff; /* Falloff */ + D3DVALUE dvAttenuation0; /* Constant attenuation */ + D3DVALUE dvAttenuation1; /* Linear attenuation */ + D3DVALUE dvAttenuation2; /* Quadratic attenuation */ + D3DVALUE dvTheta; /* Inner angle of spotlight cone */ + D3DVALUE dvPhi; /* Outer angle of spotlight cone */ +} D3DLIGHT, *LPD3DLIGHT; + +typedef struct _D3DLIGHTDATA { + DWORD dwSize; + LPD3DLIGHTINGELEMENT lpIn; /* Input positions and normals */ + DWORD dwInSize; /* Stride of input elements */ + LPD3DTLVERTEX lpOut; /* Output colors */ + DWORD dwOutSize; /* Stride of output colors */ +} D3DLIGHTDATA, *LPD3DLIGHTDATA; + +typedef enum _D3DCOLORMODEL { + D3DCOLOR_MONO = 1, + D3DCOLOR_RGB = 2, +} D3DCOLORMODEL; + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ + +/* + * Execute buffers are allocated via Direct3D. These buffers may then + * be filled by the application with instructions to execute along with + * vertex data. + */ + +/* + * Supported op codes for execute instructions. + */ +typedef enum _D3DOPCODE { + D3DOP_POINT = 1, + D3DOP_LINE = 2, + D3DOP_TRIANGLE = 3, + D3DOP_MATRIXLOAD = 4, + D3DOP_MATRIXMULTIPLY = 5, + D3DOP_STATETRANSFORM = 6, + D3DOP_STATELIGHT = 7, + D3DOP_STATERENDER = 8, + D3DOP_PROCESSVERTICES = 9, + D3DOP_TEXTURELOAD = 10, + D3DOP_EXIT = 11, + D3DOP_BRANCHFORWARD = 12, + D3DOP_SPAN = 13, + D3DOP_SETSTATUS = 14, +} D3DOPCODE; + +typedef struct _D3DINSTRUCTION { + BYTE bOpcode; /* Instruction opcode */ + BYTE bSize; /* Size of each instruction data unit */ + WORD wCount; /* Count of instruction data units to follow */ +} D3DINSTRUCTION, *LPD3DINSTRUCTION; + +/* + * Structure for texture loads + */ +typedef struct _D3DTEXTURELOAD { + D3DTEXTUREHANDLE hDestTexture; + D3DTEXTUREHANDLE hSrcTexture; +} D3DTEXTURELOAD, *LPD3DTEXTURELOAD; + +/* + * Structure for picking + */ +typedef struct _D3DPICKRECORD { + BYTE bOpcode; + BYTE bPad; + DWORD dwOffset; + D3DVALUE dvZ; +} D3DPICKRECORD, *LPD3DPICKRECORD; + +/* + * The following defines the rendering states which can be set in the + * execute buffer. + */ + +typedef enum _D3DSHADEMODE { + D3DSHADE_FLAT = 1, + D3DSHADE_GOURAUD = 2, + D3DSHADE_PHONG = 3, +} D3DSHADEMODE; + +typedef enum _D3DFILLMODE { + D3DFILL_POINT = 1, + D3DFILL_WIREFRAME = 2, + D3DFILL_SOLID = 3, +} D3DFILLMODE; + +typedef struct _D3DLINEPATTERN { + WORD wRepeatFactor; + WORD wLinePattern; +} D3DLINEPATTERN; + +typedef enum _D3DTEXTUREFILTER { + D3DFILTER_NEAREST = 1, + D3DFILTER_LINEAR = 2, + D3DFILTER_MIPNEAREST = 3, + D3DFILTER_MIPLINEAR = 4, + D3DFILTER_LINEARMIPNEAREST = 5, + D3DFILTER_LINEARMIPLINEAR = 6, +} D3DTEXTUREFILTER; + +typedef enum _D3DBLEND { + D3DBLEND_ZERO = 1, + D3DBLEND_ONE = 2, + D3DBLEND_SRCCOLOR = 3, + D3DBLEND_INVSRCCOLOR = 4, + D3DBLEND_SRCALPHA = 5, + D3DBLEND_INVSRCALPHA = 6, + D3DBLEND_DESTALPHA = 7, + D3DBLEND_INVDESTALPHA = 8, + D3DBLEND_DESTCOLOR = 9, + D3DBLEND_INVDESTCOLOR = 10, + D3DBLEND_SRCALPHASAT = 11, + D3DBLEND_BOTHSRCALPHA = 12, + D3DBLEND_BOTHINVSRCALPHA = 13, +} D3DBLEND; + +typedef enum _D3DTEXTUREBLEND { + D3DTBLEND_DECAL = 1, + D3DTBLEND_MODULATE = 2, + D3DTBLEND_DECALALPHA = 3, + D3DTBLEND_MODULATEALPHA = 4, + D3DTBLEND_DECALMASK = 5, + D3DTBLEND_MODULATEMASK = 6, + D3DTBLEND_COPY = 7, +} D3DTEXTUREBLEND; + +typedef enum _D3DTEXTUREADDRESS { + D3DTADDRESS_WRAP = 1, + D3DTADDRESS_MIRROR = 2, + D3DTADDRESS_CLAMP = 3, +} D3DTEXTUREADDRESS; + +typedef enum _D3DCULL { + D3DCULL_NONE = 1, + D3DCULL_CW = 2, + D3DCULL_CCW = 3, +} D3DCULL; + +typedef enum _D3DCMPFUNC { + D3DCMP_NEVER = 1, + D3DCMP_LESS = 2, + D3DCMP_EQUAL = 3, + D3DCMP_LESSEQUAL = 4, + D3DCMP_GREATER = 5, + D3DCMP_NOTEQUAL = 6, + D3DCMP_GREATEREQUAL = 7, + D3DCMP_ALWAYS = 8, +} D3DCMPFUNC; + +typedef enum _D3DFOGMODE { + D3DFOG_NONE = 0, + D3DFOG_EXP = 1, + D3DFOG_EXP2 = 2, + D3DFOG_LINEAR = 3 +} D3DFOGMODE; + +/* + * Amount to add to a state to generate the override for that state. + */ +#define D3DSTATE_OVERRIDE_BIAS 256 + +/* + * A state which sets the override flag for the specified state type. + */ +#define D3DSTATE_OVERRIDE(type) ((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS) + +typedef enum _D3DTRANSFORMSTATETYPE { + D3DTRANSFORMSTATE_WORLD = 1, + D3DTRANSFORMSTATE_VIEW = 2, + D3DTRANSFORMSTATE_PROJECTION = 3, +} D3DTRANSFORMSTATETYPE; + +typedef enum _D3DLIGHTSTATETYPE { + D3DLIGHTSTATE_MATERIAL = 1, + D3DLIGHTSTATE_AMBIENT = 2, + D3DLIGHTSTATE_COLORMODEL = 3, + D3DLIGHTSTATE_FOGMODE = 4, + D3DLIGHTSTATE_FOGSTART = 5, + D3DLIGHTSTATE_FOGEND = 6, + D3DLIGHTSTATE_FOGDENSITY = 7, +} D3DLIGHTSTATETYPE; + +typedef enum _D3DRENDERSTATETYPE { + D3DRENDERSTATE_TEXTUREHANDLE = 1, /* Texture handle */ + D3DRENDERSTATE_ANTIALIAS = 2, /* Antialiasing prim edges */ + D3DRENDERSTATE_TEXTUREADDRESS = 3, /* D3DTEXTUREADDRESS */ + D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4, /* TRUE for perspective correction */ + D3DRENDERSTATE_WRAPU = 5, /* TRUE for wrapping in u */ + D3DRENDERSTATE_WRAPV = 6, /* TRUE for wrapping in v */ + D3DRENDERSTATE_ZENABLE = 7, /* TRUE to enable z test */ + D3DRENDERSTATE_FILLMODE = 8, /* D3DFILL_MODE */ + D3DRENDERSTATE_SHADEMODE = 9, /* D3DSHADEMODE */ + D3DRENDERSTATE_LINEPATTERN = 10, /* D3DLINEPATTERN */ + D3DRENDERSTATE_MONOENABLE = 11, /* TRUE to enable mono rasterization */ + D3DRENDERSTATE_ROP2 = 12, /* ROP2 */ + D3DRENDERSTATE_PLANEMASK = 13, /* DWORD physical plane mask */ + D3DRENDERSTATE_ZWRITEENABLE = 14, /* TRUE to enable z writes */ + D3DRENDERSTATE_ALPHATESTENABLE = 15, /* TRUE to enable alpha tests */ + D3DRENDERSTATE_LASTPIXEL = 16, /* TRUE for last-pixel on lines */ + D3DRENDERSTATE_TEXTUREMAG = 17, /* D3DTEXTUREFILTER */ + D3DRENDERSTATE_TEXTUREMIN = 18, /* D3DTEXTUREFILTER */ + D3DRENDERSTATE_SRCBLEND = 19, /* D3DBLEND */ + D3DRENDERSTATE_DESTBLEND = 20, /* D3DBLEND */ + D3DRENDERSTATE_TEXTUREMAPBLEND = 21, /* D3DTEXTUREBLEND */ + D3DRENDERSTATE_CULLMODE = 22, /* D3DCULL */ + D3DRENDERSTATE_ZFUNC = 23, /* D3DCMPFUNC */ + D3DRENDERSTATE_ALPHAREF = 24, /* D3DFIXED */ + D3DRENDERSTATE_ALPHAFUNC = 25, /* D3DCMPFUNC */ + D3DRENDERSTATE_DITHERENABLE = 26, /* TRUE to enable dithering */ + D3DRENDERSTATE_BLENDENABLE = 27, /* TRUE to enable alpha blending */ + D3DRENDERSTATE_FOGENABLE = 28, /* TRUE to enable fog */ + D3DRENDERSTATE_SPECULARENABLE = 29, /* TRUE to enable specular */ + D3DRENDERSTATE_ZVISIBLE = 30, /* TRUE to enable z checking */ + D3DRENDERSTATE_SUBPIXEL = 31, /* TRUE to enable subpixel correction */ + D3DRENDERSTATE_SUBPIXELX = 32, /* TRUE to enable correction in X only */ + D3DRENDERSTATE_STIPPLEDALPHA = 33, /* TRUE to enable stippled alpha */ + D3DRENDERSTATE_FOGCOLOR = 34, /* D3DCOLOR */ + D3DRENDERSTATE_FOGTABLEMODE = 35, /* D3DFOGMODE */ + D3DRENDERSTATE_FOGTABLESTART = 36, /* Fog table start */ + D3DRENDERSTATE_FOGTABLEEND = 37, /* Fog table end */ + D3DRENDERSTATE_FOGTABLEDENSITY = 38, /* Fog table density */ + D3DRENDERSTATE_STIPPLEENABLE = 39, /* TRUE to enable stippling */ + D3DRENDERSTATE_STIPPLEPATTERN00 = 64, /* Stipple pattern 01... */ + D3DRENDERSTATE_STIPPLEPATTERN01 = 65, + D3DRENDERSTATE_STIPPLEPATTERN02 = 66, + D3DRENDERSTATE_STIPPLEPATTERN03 = 67, + D3DRENDERSTATE_STIPPLEPATTERN04 = 68, + D3DRENDERSTATE_STIPPLEPATTERN05 = 69, + D3DRENDERSTATE_STIPPLEPATTERN06 = 70, + D3DRENDERSTATE_STIPPLEPATTERN07 = 71, + D3DRENDERSTATE_STIPPLEPATTERN08 = 72, + D3DRENDERSTATE_STIPPLEPATTERN09 = 73, + D3DRENDERSTATE_STIPPLEPATTERN10 = 74, + D3DRENDERSTATE_STIPPLEPATTERN11 = 75, + D3DRENDERSTATE_STIPPLEPATTERN12 = 76, + D3DRENDERSTATE_STIPPLEPATTERN13 = 77, + D3DRENDERSTATE_STIPPLEPATTERN14 = 78, + D3DRENDERSTATE_STIPPLEPATTERN15 = 79, + D3DRENDERSTATE_STIPPLEPATTERN16 = 80, + D3DRENDERSTATE_STIPPLEPATTERN17 = 81, + D3DRENDERSTATE_STIPPLEPATTERN18 = 82, + D3DRENDERSTATE_STIPPLEPATTERN19 = 83, + D3DRENDERSTATE_STIPPLEPATTERN20 = 84, + D3DRENDERSTATE_STIPPLEPATTERN21 = 85, + D3DRENDERSTATE_STIPPLEPATTERN22 = 86, + D3DRENDERSTATE_STIPPLEPATTERN23 = 87, + D3DRENDERSTATE_STIPPLEPATTERN24 = 88, + D3DRENDERSTATE_STIPPLEPATTERN25 = 89, + D3DRENDERSTATE_STIPPLEPATTERN26 = 90, + D3DRENDERSTATE_STIPPLEPATTERN27 = 91, + D3DRENDERSTATE_STIPPLEPATTERN28 = 92, + D3DRENDERSTATE_STIPPLEPATTERN29 = 93, + D3DRENDERSTATE_STIPPLEPATTERN30 = 94, + D3DRENDERSTATE_STIPPLEPATTERN31 = 95, +} D3DRENDERSTATETYPE; + +#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y)) + +typedef struct _D3DSTATE { + union { + D3DTRANSFORMSTATETYPE dtstTransformStateType; + D3DLIGHTSTATETYPE dlstLightStateType; + D3DRENDERSTATETYPE drstRenderStateType; + }; + union { + DWORD dwArg[1]; + D3DVALUE dvArg[1]; + }; +} D3DSTATE, *LPD3DSTATE; + +/* + * Operation used to load matrices + * hDstMat = hSrcMat + */ +typedef struct _D3DMATRIXLOAD { + D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ + D3DMATRIXHANDLE hSrcMatrix; /* Source matrix */ +} D3DMATRIXLOAD, *LPD3DMATRIXLOAD; + +/* + * Operation used to multiply matrices + * hDstMat = hSrcMat1 * hSrcMat2 + */ +typedef struct _D3DMATRIXMULTIPLY { + D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ + D3DMATRIXHANDLE hSrcMatrix1; /* First source matrix */ + D3DMATRIXHANDLE hSrcMatrix2; /* Second source matrix */ +} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY; + +/* + * Operation used to transform and light vertices. + */ +typedef struct _D3DPROCESSVERTICES { + DWORD dwFlags; /* Do we transform or light or just copy? */ + WORD wStart; /* Index to first vertex in source */ + WORD wDest; /* Index to first vertex in local buffer */ + DWORD dwCount; /* Number of vertices to be processed */ + DWORD dwReserved; /* Must be zero */ +} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES; + +#define D3DPROCESSVERTICES_TRANSFORMLIGHT 0x00000000L +#define D3DPROCESSVERTICES_TRANSFORM 0x00000001L +#define D3DPROCESSVERTICES_COPY 0x00000002L +#define D3DPROCESSVERTICES_OPMASK 0x00000007L + +#define D3DPROCESSVERTICES_UPDATEEXTENTS 0x00000008L +#define D3DPROCESSVERTICES_NOCOLOR 0x00000010L + + +/* + * Triangle flags + */ + +/* + * Tri strip and fan flags. + * START loads all three vertices + * EVEN and ODD load just v3 with even or odd culling + * START_FLAT contains a count from 0 to 29 that allows the + * whole strip or fan to be culled in one hit. + * e.g. for a quad len = 1 + */ +#define D3DTRIFLAG_START 0x00000000L +#define D3DTRIFLAG_STARTFLAT(len) (len) /* 0 < len < 30 */ +#define D3DTRIFLAG_ODD 0x0000001eL +#define D3DTRIFLAG_EVEN 0x0000001fL + +/* + * Triangle edge flags + * enable edges for wireframe or antialiasing + */ +#define D3DTRIFLAG_EDGEENABLE1 0x00000100L /* v0-v1 edge */ +#define D3DTRIFLAG_EDGEENABLE2 0x00000200L /* v1-v2 edge */ +#define D3DTRIFLAG_EDGEENABLE3 0x00000400L /* v2-v0 edge */ +#define D3DTRIFLAG_EDGEENABLETRIANGLE \ + (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3) + +/* + * Primitive structures and related defines. Vertex offsets are to types + * D3DVERTEX, D3DLVERTEX, or D3DTLVERTEX. + */ + +/* + * Triangle list primitive structure + */ +typedef struct _D3DTRIANGLE { + union { + WORD v1; /* Vertex indices */ + WORD wV1; + }; + union { + WORD v2; + WORD wV2; + }; + union { + WORD v3; + WORD wV3; + }; + WORD wFlags; /* Edge (and other) flags */ +} D3DTRIANGLE, *LPD3DTRIANGLE; + +/* + * Line strip structure. + * The instruction count - 1 defines the number of line segments. + */ +typedef struct _D3DLINE { + union { + WORD v1; /* Vertex indices */ + WORD wV1; + }; + union { + WORD v2; + WORD wV2; + }; +} D3DLINE, *LPD3DLINE; + +/* + * Span structure + * Spans join a list of points with the same y value. + * If the y value changes, a new span is started. + */ +typedef struct _D3DSPAN { + WORD wCount; /* Number of spans */ + WORD wFirst; /* Index to first vertex */ +} D3DSPAN, *LPD3DSPAN; + +/* + * Point structure + */ +typedef struct _D3DPOINT { + WORD wCount; /* number of points */ + WORD wFirst; /* index to first vertex */ +} D3DPOINT, *LPD3DPOINT; + + +/* + * Forward branch structure. + * Mask is logically anded with the driver status mask + * if the result equals 'value', the branch is taken. + */ +typedef struct _D3DBRANCH { + DWORD dwMask; /* Bitmask against D3D status */ + DWORD dwValue; + BOOL bNegate; /* TRUE to negate comparison */ + DWORD dwOffset; /* How far to branch forward (0 for exit)*/ +} D3DBRANCH, *LPD3DBRANCH; + +/* + * Status used for set status instruction. + * The D3D status is initialised on device creation + * and is modified by all execute calls. + */ +typedef struct _D3DSTATUS { + DWORD dwFlags; /* Do we set extents or status */ + DWORD dwStatus; /* D3D status */ + D3DRECT drExtent; +} D3DSTATUS, *LPD3DSTATUS; + +#define D3DSETSTATUS_STATUS 0x00000001L +#define D3DSETSTATUS_EXTENTS 0x00000002L +#define D3DSETSTATUS_ALL (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS) + +/* + * Statistics structure + */ +typedef struct _D3DSTATS { + DWORD dwSize; + DWORD dwTrianglesDrawn; + DWORD dwLinesDrawn; + DWORD dwPointsDrawn; + DWORD dwSpansDrawn; + DWORD dwVerticesProcessed; +} D3DSTATS, *LPD3DSTATS; + +/* + * Execute options. + * When calling using D3DEXECUTE_UNCLIPPED all the primitives + * inside the buffer must be contained within the viewport. + */ +#define D3DEXECUTE_CLIPPED 0x00000001l +#define D3DEXECUTE_UNCLIPPED 0x00000002l + +typedef struct _D3DEXECUTEDATA { + DWORD dwSize; + DWORD dwVertexOffset; + DWORD dwVertexCount; + DWORD dwInstructionOffset; + DWORD dwInstructionLength; + DWORD dwHVertexOffset; + D3DSTATUS dsStatus; /* Status after execute */ +} D3DEXECUTEDATA, *LPD3DEXECUTEDATA; + +/* + * Palette flags. + * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw. + */ +#define D3DPAL_FREE 0x00 /* Renderer may use this entry freely */ +#define D3DPAL_READONLY 0x40 /* Renderer may not set this entry */ +#define D3DPAL_RESERVED 0x80 /* Renderer may not use this entry */ + +#if defined(__cplusplus) +}; +#endif + +#pragma pack() + +#endif /* _D3DTYPES_H_ */ diff --git a/WinQuake/dxsdk/SDK/INC/DDRAW.H b/WinQuake/dxsdk/SDK/INC/DDRAW.H index abb9104..04649ff 100644 --- a/WinQuake/dxsdk/SDK/INC/DDRAW.H +++ b/WinQuake/dxsdk/SDK/INC/DDRAW.H @@ -1,3102 +1,3102 @@ -/*==========================================================================; - * - * Copyright (C) 1994-1996 Microsoft Corporation. All Rights Reserved. - * - * File: ddraw.h - * Content: DirectDraw include file - * - ***************************************************************************/ - -#ifndef __DDRAW_INCLUDED__ -#define __DDRAW_INCLUDED__ -#if defined( _WIN32 ) && !defined( _NO_COM ) -#define COM_NO_WINDOWS_H -#include -#else -#define IUnknown void -#define CO_E_NOTINITIALIZED 0x800401F0L -#endif - -#define _FACDD 0x876 -#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * GUIDS used by DirectDraw objects - */ -#if defined( _WIN32 ) && !defined( _NO_COM ) -DEFINE_GUID( CLSID_DirectDraw, 0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 ); -DEFINE_GUID( CLSID_DirectDrawClipper, 0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 ); -DEFINE_GUID( IID_IDirectDraw, 0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 ); -DEFINE_GUID( IID_IDirectDrawSurface, 0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 ); - -DEFINE_GUID( IID_IDirectDrawPalette, 0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDrawClipper, 0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); - -#endif - -/*============================================================================ - * - * DirectDraw Structures - * - * Various structures used to invoke DirectDraw. - * - *==========================================================================*/ - -struct IDirectDraw; -struct IDirectDrawSurface; -struct IDirectDrawPalette; -struct IDirectDrawClipper; - -typedef struct IDirectDraw FAR *LPDIRECTDRAW; -typedef struct IDirectDraw2 FAR *LPDIRECTDRAW2; -typedef struct IDirectDrawSurface FAR *LPDIRECTDRAWSURFACE; -typedef struct IDirectDrawSurface2 FAR *LPDIRECTDRAWSURFACE2; - -typedef struct IDirectDrawPalette FAR *LPDIRECTDRAWPALETTE; -typedef struct IDirectDrawClipper FAR *LPDIRECTDRAWCLIPPER; - -typedef struct _DDFXROP FAR *LPDDFXROP; -typedef struct _DDSURFACEDESC FAR *LPDDSURFACEDESC; - -/* - * API's - */ -#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM ) -//#if defined( _WIN32 ) && !defined( _NO_ENUM ) - typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID); - typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID); - extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext ); - extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext ); - #ifdef UNICODE - typedef LPDDENUMCALLBACKW LPDDENUMCALLBACK; - #define DirectDrawEnumerate DirectDrawEnumerateW - #else - typedef LPDDENUMCALLBACKA LPDDENUMCALLBACK; - #define DirectDrawEnumerate DirectDrawEnumerateA - #endif - extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); - extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter ); - #ifdef WINNT - //This is the user-mode entry stub to the kernel mode procedure. - extern HRESULT NtDirectDrawCreate( GUID FAR *lpGUID, HANDLE *lplpDD, IUnknown FAR *pUnkOuter ); - #endif -#endif - -#define REGSTR_KEY_DDHW_DESCRIPTION "Description" -#define REGSTR_KEY_DDHW_DRIVERNAME "DriverName" -#define REGSTR_PATH_DDHW "Hardware\\DirectDrawDrivers" - -#define DDCREATE_HARDWAREONLY 0x00000001l -#define DDCREATE_EMULATIONONLY 0x00000002l - -#ifdef WINNT -typedef long HRESULT; -#endif - -//#ifndef WINNT -typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID); -typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID); -//#endif -/* - * DDCOLORKEY - */ -typedef struct _DDCOLORKEY -{ - DWORD dwColorSpaceLowValue; // low boundary of color space that is to - // be treated as Color Key, inclusive - DWORD dwColorSpaceHighValue; // high boundary of color space that is - // to be treated as Color Key, inclusive -} DDCOLORKEY; - -typedef DDCOLORKEY FAR* LPDDCOLORKEY; - -/* - * DDBLTFX - * Used to pass override information to the DIRECTDRAWSURFACE callback Blt. - */ -typedef struct _DDBLTFX -{ - DWORD dwSize; // size of structure - DWORD dwDDFX; // FX operations - DWORD dwROP; // Win32 raster operations - DWORD dwDDROP; // Raster operations new for DirectDraw - DWORD dwRotationAngle; // Rotation angle for blt - DWORD dwZBufferOpCode; // ZBuffer compares - DWORD dwZBufferLow; // Low limit of Z buffer - DWORD dwZBufferHigh; // High limit of Z buffer - DWORD dwZBufferBaseDest; // Destination base value - DWORD dwZDestConstBitDepth; // Bit depth used to specify Z constant for destination - union - { - DWORD dwZDestConst; // Constant to use as Z buffer for dest - LPDIRECTDRAWSURFACE lpDDSZBufferDest; // Surface to use as Z buffer for dest - }; - DWORD dwZSrcConstBitDepth; // Bit depth used to specify Z constant for source - union - { - DWORD dwZSrcConst; // Constant to use as Z buffer for src - LPDIRECTDRAWSURFACE lpDDSZBufferSrc; // Surface to use as Z buffer for src - }; - DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend - DWORD dwAlphaEdgeBlend; // Alpha for edge blending - DWORD dwReserved; - DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination - union - { - DWORD dwAlphaDestConst; // Constant to use as Alpha Channel - LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as Alpha Channel - }; - DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source - union - { - DWORD dwAlphaSrcConst; // Constant to use as Alpha Channel - LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as Alpha Channel - }; - union - { - DWORD dwFillColor; // color in RGB or Palettized - DWORD dwFillDepth; // depth value for z-buffer - LPDIRECTDRAWSURFACE lpDDSPattern; // Surface to use as pattern - }; - DDCOLORKEY ddckDestColorkey; // DestColorkey override - DDCOLORKEY ddckSrcColorkey; // SrcColorkey override -} DDBLTFX; - -typedef DDBLTFX FAR* LPDDBLTFX; - - -/* - * DDSCAPS - */ -typedef struct _DDSCAPS -{ - DWORD dwCaps; // capabilities of surface wanted -} DDSCAPS; - -typedef DDSCAPS FAR* LPDDSCAPS; - -/* - * DDCAPS - */ -#define DD_ROP_SPACE (256/32) // space required to store ROP array - -typedef struct _DDCAPS -{ - DWORD dwSize; // size of the DDDRIVERCAPS structure - DWORD dwCaps; // driver specific capabilities - DWORD dwCaps2; // more driver specific capabilites - DWORD dwCKeyCaps; // color key capabilities of the surface - DWORD dwFXCaps; // driver specific stretching and effects capabilites - DWORD dwFXAlphaCaps; // alpha driver specific capabilities - DWORD dwPalCaps; // palette capabilities - DWORD dwSVCaps; // stereo vision capabilities - DWORD dwAlphaBltConstBitDepths; // DDBD_2,4,8 - DWORD dwAlphaBltPixelBitDepths; // DDBD_1,2,4,8 - DWORD dwAlphaBltSurfaceBitDepths; // DDBD_1,2,4,8 - DWORD dwAlphaOverlayConstBitDepths; // DDBD_2,4,8 - DWORD dwAlphaOverlayPixelBitDepths; // DDBD_1,2,4,8 - DWORD dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8 - DWORD dwZBufferBitDepths; // DDBD_8,16,24,32 - DWORD dwVidMemTotal; // total amount of video memory - DWORD dwVidMemFree; // amount of free video memory - DWORD dwMaxVisibleOverlays; // maximum number of visible overlays - DWORD dwCurrVisibleOverlays; // current number of visible overlays - DWORD dwNumFourCCCodes; // number of four cc codes - DWORD dwAlignBoundarySrc; // source rectangle alignment - DWORD dwAlignSizeSrc; // source rectangle byte size - DWORD dwAlignBoundaryDest; // dest rectangle alignment - DWORD dwAlignSizeDest; // dest rectangle byte size - DWORD dwAlignStrideAlign; // stride alignment - DWORD dwRops[DD_ROP_SPACE]; // ROPS supported - DDSCAPS ddsCaps; // DDSCAPS structure has all the general capabilities - DWORD dwMinOverlayStretch; // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwMaxOverlayStretch; // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwMinLiveVideoStretch; // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwMaxLiveVideoStretch; // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwMinHwCodecStretch; // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwMaxHwCodecStretch; // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 - DWORD dwReserved1; // reserved - DWORD dwReserved2; // reserved - DWORD dwReserved3; // reserved - DWORD dwSVBCaps; // driver specific capabilities for System->Vmem blts - DWORD dwSVBCKeyCaps; // driver color key capabilities for System->Vmem blts - DWORD dwSVBFXCaps; // driver FX capabilities for System->Vmem blts - DWORD dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts - DWORD dwVSBCaps; // driver specific capabilities for Vmem->System blts - DWORD dwVSBCKeyCaps; // driver color key capabilities for Vmem->System blts - DWORD dwVSBFXCaps; // driver FX capabilities for Vmem->System blts - DWORD dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts - DWORD dwSSBCaps; // driver specific capabilities for System->System blts - DWORD dwSSBCKeyCaps; // driver color key capabilities for System->System blts - DWORD dwSSBFXCaps; // driver FX capabilities for System->System blts - DWORD dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts - DWORD dwReserved4; // reserved - DWORD dwReserved5; // reserved - DWORD dwReserved6; // reserved -} DDCAPS; - -typedef DDCAPS FAR* LPDDCAPS; - - - -/* - * DDPIXELFORMAT - */ -typedef struct _DDPIXELFORMAT -{ - DWORD dwSize; // size of structure - DWORD dwFlags; // pixel format flags - DWORD dwFourCC; // (FOURCC code) - union - { - DWORD dwRGBBitCount; // how many bits per pixel (BD_4,8,16,24,32) - DWORD dwYUVBitCount; // how many bits per pixel (BD_4,8,16,24,32) - DWORD dwZBufferBitDepth; // how many bits for z buffers (BD_8,16,24,32) - DWORD dwAlphaBitDepth; // how many bits for alpha channels (BD_1,2,4,8) - }; - union - { - DWORD dwRBitMask; // mask for red bit - DWORD dwYBitMask; // mask for Y bits - }; - union - { - DWORD dwGBitMask; // mask for green bits - DWORD dwUBitMask; // mask for U bits - }; - union - { - DWORD dwBBitMask; // mask for blue bits - DWORD dwVBitMask; // mask for V bits - }; - union - { - DWORD dwRGBAlphaBitMask; // mask for alpha channel - DWORD dwYUVAlphaBitMask; // mask for alpha channel - }; -} DDPIXELFORMAT; - -typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT; - -/* - * DDOVERLAYFX - */ -typedef struct _DDOVERLAYFX -{ - DWORD dwSize; // size of structure - DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend - DWORD dwAlphaEdgeBlend; // Constant to use as alpha for edge blend - DWORD dwReserved; - DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination - union - { - DWORD dwAlphaDestConst; // Constant to use as alpha channel for dest - LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as alpha channel for dest - }; - DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source - union - { - DWORD dwAlphaSrcConst; // Constant to use as alpha channel for src - LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as alpha channel for src - }; - DDCOLORKEY dckDestColorkey; // DestColorkey override - DDCOLORKEY dckSrcColorkey; // DestColorkey override - DWORD dwDDFX; // Overlay FX - DWORD dwFlags; // flags -} DDOVERLAYFX; - -typedef DDOVERLAYFX FAR *LPDDOVERLAYFX; - -/* - * DDBLTBATCH: BltBatch entry structure - */ -typedef struct _DDBLTBATCH -{ - LPRECT lprDest; - LPDIRECTDRAWSURFACE lpDDSSrc; - LPRECT lprSrc; - DWORD dwFlags; - LPDDBLTFX lpDDBltFx; -} DDBLTBATCH; - -typedef DDBLTBATCH FAR * LPDDBLTBATCH; - -/* - * callbacks - */ -typedef DWORD (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext ); -#ifdef STREAMING -typedef DWORD (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD); -#endif - - -/* - * INTERACES FOLLOW: - * IDirectDraw - * IDirectDrawClipper - * IDirectDrawPalette - * IDirectDrawSurface - */ - -/* - * IDirectDraw - */ -#if defined( _WIN32 ) && !defined( _NO_COM ) -#undef INTERFACE -#define INTERFACE IDirectDraw -DECLARE_INTERFACE_( IDirectDraw, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDraw methods ***/ - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; - STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; - STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; - STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; - STDMETHOD(FlipToGDISurface)(THIS) PURE; - STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; - STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; - STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; - STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; - STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; - STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; - STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; - STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; - STDMETHOD(RestoreDisplayMode)(THIS) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; - STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE; - STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDraw_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirectDraw_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDraw_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) -#define IDirectDraw_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) -#define IDirectDraw_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) -#define IDirectDraw_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) -#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) -#define IDirectDraw_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) -#define IDirectDraw_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) -#define IDirectDraw_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) -#define IDirectDraw_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) -#define IDirectDraw_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) -#define IDirectDraw_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) -#define IDirectDraw_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) -#define IDirectDraw_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) -#define IDirectDraw_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirectDraw_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) -#define IDirectDraw_SetDisplayMode(p, a, b, c) (p)->lpVtbl->SetDisplayMode(p, a, b, c) -#define IDirectDraw_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) -#endif - -#endif - -#if defined( _WIN32 ) && !defined( _NO_COM ) -#undef INTERFACE -#define INTERFACE IDirectDraw2 -DECLARE_INTERFACE_( IDirectDraw2, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDraw methods ***/ - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; - STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; - STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; - STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; - STDMETHOD(FlipToGDISurface)(THIS) PURE; - STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; - STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; - STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; - STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; - STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; - STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; - STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; - STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; - STDMETHOD(RestoreDisplayMode)(THIS) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; - STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE; - STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; - /*** Added in the v2 interface ***/ - STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE; -}; -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDraw2_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirectDraw2_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw2_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDraw2_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw2_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) -#define IDirectDraw2_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) -#define IDirectDraw2_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) -#define IDirectDraw2_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) -#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) -#define IDirectDraw2_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) -#define IDirectDraw2_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw2_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) -#define IDirectDraw2_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) -#define IDirectDraw2_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) -#define IDirectDraw2_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) -#define IDirectDraw2_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) -#define IDirectDraw2_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) -#define IDirectDraw2_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) -#define IDirectDraw2_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) -#define IDirectDraw2_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw2_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) -#define IDirectDraw2_SetDisplayMode(p, a, b, c, d) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d) -#define IDirectDraw2_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) -#define IDirectDraw2_GetAvailableVidMem(p, a, b, c) (p)->lpVtbl->GetAvailableVidMem(p, a, b, c) -#endif - -#endif - -/* - * IDirectDrawPalette - */ -#if defined( _WIN32 ) && !defined( _NO_COM ) -#undef INTERFACE -#define INTERFACE IDirectDrawPalette -DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDrawPalette methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE; - STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE; - STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDrawPalette_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirectDrawPalette_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawPalette_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDrawPalette_GetCaps(p, a) (p)->lpVtbl->GetCaps(p, a) -#define IDirectDrawPalette_GetEntries(p, a, b, c, d) (p)->lpVtbl->GetEntries(p, a, b, c, d) -#define IDirectDrawPalette_Initialize(p, a, b, c) (p)->lpVtbl->Initialize(p, a, b, c) -#define IDirectDrawPalette_SetEntries(p, a, b, c, d) (p)->lpVtbl->SetEntries(p, a, b, c, d) -#endif - -#endif - -/* - * IDirectDrawClipper - */ -#if defined( _WIN32 ) && !defined( _NO_COM ) -#undef INTERFACE -#define INTERFACE IDirectDrawClipper -DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDrawClipper methods ***/ - STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE; - STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE; - STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE; - STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE; - STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDrawClipper_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) -#define IDirectDrawClipper_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawClipper_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDrawClipper_GetClipList(p, a, b, c) (p)->lpVtbl->GetClipList(p, a, b, c) -#define IDirectDrawClipper_GetHWnd(p, a) (p)->lpVtbl->GetHWnd(p, a) -#define IDirectDrawClipper_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) -#define IDirectDrawClipper_IsClipListChanged(p, a) (p)->lpVtbl->IsClipListChanged(p, a) -#define IDirectDrawClipper_SetClipList(p, a, b) (p)->lpVtbl->SetClipList(p, a, b) -#define IDirectDrawClipper_SetHWnd(p, a, b) (p)->lpVtbl->SetHWnd(p, a, b) -#endif - -#endif - -/* - * IDirectDrawSurface and related interfaces - */ -#if defined( _WIN32 ) && !defined( _NO_COM ) -#undef INTERFACE -#define INTERFACE IDirectDrawSurface -DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDrawSurface methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; - STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; - STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; - STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDrawSurface_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDrawSurface_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) -#define IDirectDrawSurface_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) -#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -#endif - -/* - * IDirectDrawSurface2 and related interfaces - */ -#undef INTERFACE -#define INTERFACE IDirectDrawSurface2 -DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectDrawSurface methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; - STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; - STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; - STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE; - /*** Added in the v2 interface ***/ - STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE; - STDMETHOD(PageLock)(THIS_ DWORD) PURE; - STDMETHOD(PageUnlock)(THIS_ DWORD) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectDrawSurface2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface2_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface2_Release(p) (p)->lpVtbl->Release(p) -#define IDirectDrawSurface2_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface2_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface2_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface2_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface2_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface2_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface2_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) -#define IDirectDrawSurface2_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface2_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface2_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface2_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface2_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface2_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface2_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface2_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface2_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface2_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface2_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface2_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface2_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface2_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface2_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface2_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface2_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) -#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -#define IDirectDrawSurface2_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) -#define IDirectDrawSurface2_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) -#define IDirectDrawSurface2_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) -#endif - - -#endif - - -/* - * DDSURFACEDESC - */ -typedef struct _DDSURFACEDESC -{ - DWORD dwSize; // size of the DDSURFACEDESC structure - DWORD dwFlags; // determines what fields are valid - DWORD dwHeight; // height of surface to be created - DWORD dwWidth; // width of input surface - LONG lPitch; // distance to start of next line (return value only) - DWORD dwBackBufferCount; // number of back buffers requested - union - { - DWORD dwMipMapCount; // number of mip-map levels requested - DWORD dwZBufferBitDepth; // depth of Z buffer requested - DWORD dwRefreshRate; // refresh rate (used when display mode is described) - }; - DWORD dwAlphaBitDepth; // depth of alpha buffer requested - DWORD dwReserved; // reserved - LPVOID lpSurface; // pointer to the associated surface memory - DDCOLORKEY ddckCKDestOverlay; // color key for destination overlay use - DDCOLORKEY ddckCKDestBlt; // color key for destination blt use - DDCOLORKEY ddckCKSrcOverlay; // color key for source overlay use - DDCOLORKEY ddckCKSrcBlt; // color key for source blt use - DDPIXELFORMAT ddpfPixelFormat; // pixel format description of the surface - DDSCAPS ddsCaps; // direct draw surface capabilities -} DDSURFACEDESC; - -/* - * ddsCaps field is valid. - */ -#define DDSD_CAPS 0x00000001l // default - -/* - * dwHeight field is valid. - */ -#define DDSD_HEIGHT 0x00000002l - -/* - * dwWidth field is valid. - */ -#define DDSD_WIDTH 0x00000004l - -/* - * lPitch is valid. - */ -#define DDSD_PITCH 0x00000008l - -/* - * dwBackBufferCount is valid. - */ -#define DDSD_BACKBUFFERCOUNT 0x00000020l - -/* - * dwZBufferBitDepth is valid. - */ -#define DDSD_ZBUFFERBITDEPTH 0x00000040l - -/* - * dwAlphaBitDepth is valid. - */ -#define DDSD_ALPHABITDEPTH 0x00000080l - - - -/* - * ddpfPixelFormat is valid. - */ -#define DDSD_PIXELFORMAT 0x00001000l - -/* - * ddckCKDestOverlay is valid. - */ -#define DDSD_CKDESTOVERLAY 0x00002000l - -/* - * ddckCKDestBlt is valid. - */ -#define DDSD_CKDESTBLT 0x00004000l - -/* - * ddckCKSrcOverlay is valid. - */ -#define DDSD_CKSRCOVERLAY 0x00008000l - -/* - * ddckCKSrcBlt is valid. - */ -#define DDSD_CKSRCBLT 0x00010000l - -/* - * dwMipMapCount is valid. - */ -#define DDSD_MIPMAPCOUNT 0x00020000l - - /* - * dwRefreshRate is valid - */ -#define DDSD_REFRESHRATE 0x00040000l - - -/* - * All input fields are valid. - */ -#define DDSD_ALL 0x0007f9eel - - -/*============================================================================ - * - * Direct Draw Capability Flags - * - * These flags are used to describe the capabilities of a given Surface. - * All flags are bit flags. - * - *==========================================================================*/ - -/**************************************************************************** - * - * DIRECTDRAWSURFACE CAPABILITY FLAGS - * - ****************************************************************************/ -/* - * This bit currently has no meaning. - */ -#define DDSCAPS_3D 0x00000001l - -/* - * Indicates that this surface contains alpha information. The pixel - * format must be interrogated to determine whether this surface - * contains only alpha information or alpha information interlaced - * with pixel color data (e.g. RGBA or YUVA). - */ -#define DDSCAPS_ALPHA 0x00000002l - -/* - * Indicates that this surface is a backbuffer. It is generally - * set by CreateSurface when the DDSCAPS_FLIP capability bit is set. - * It indicates that this surface is THE back buffer of a surface - * flipping structure. DirectDraw supports N surfaces in a - * surface flipping structure. Only the surface that immediately - * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set. - * The other surfaces are identified as back buffers by the presence - * of the DDSCAPS_FLIP capability, their attachment order, and the - * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER - * capabilities. The bit is sent to CreateSurface when a standalone - * back buffer is being created. This surface could be attached to - * a front buffer and/or back buffers to form a flipping surface - * structure after the CreateSurface call. See AddAttachments for - * a detailed description of the behaviors in this case. - */ -#define DDSCAPS_BACKBUFFER 0x00000004l - -/* - * Indicates a complex surface structure is being described. A - * complex surface structure results in the creation of more than - * one surface. The additional surfaces are attached to the root - * surface. The complex structure can only be destroyed by - * destroying the root. - */ -#define DDSCAPS_COMPLEX 0x00000008l - -/* - * Indicates that this surface is a part of a surface flipping structure. - * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and - * DDSCAP_BACKBUFFER bits are not set. They are set by CreateSurface - * on the resulting creations. The dwBackBufferCount field in the - * DDSURFACEDESC structure must be set to at least 1 in order for - * the CreateSurface call to succeed. The DDSCAPS_COMPLEX capability - * must always be set with creating multiple surfaces through CreateSurface. - */ -#define DDSCAPS_FLIP 0x00000010l - -/* - * Indicates that this surface is THE front buffer of a surface flipping - * structure. It is generally set by CreateSurface when the DDSCAPS_FLIP - * capability bit is set. - * If this capability is sent to CreateSurface then a standalonw front buffer - * is created. This surface will not have the DDSCAPS_FLIP capability. - * It can be attached to other back buffers to form a flipping structure. - * See AddAttachments for a detailed description of the behaviors in this - * case. - */ -#define DDSCAPS_FRONTBUFFER 0x00000020l - -/* - * Indicates that this surface is any offscreen surface that is not an overlay, - * texture, zbuffer, front buffer, back buffer, or alpha surface. It is used - * to identify plain vanilla surfaces. - */ -#define DDSCAPS_OFFSCREENPLAIN 0x00000040l - -/* - * Indicates that this surface is an overlay. It may or may not be directly visible - * depending on whether or not it is currently being overlayed onto the primary - * surface. DDSCAPS_VISIBLE can be used to determine whether or not it is being - * overlayed at the moment. - */ -#define DDSCAPS_OVERLAY 0x00000080l - -/* - * Indicates that unique DirectDrawPalette objects can be created and - * attached to this surface. - */ -#define DDSCAPS_PALETTE 0x00000100l - -/* - * Indicates that this surface is the primary surface. The primary - * surface represents what the user is seeing at the moment. - */ -#define DDSCAPS_PRIMARYSURFACE 0x00000200l - -/* - * Indicates that this surface is the primary surface for the left eye. - * The primary surface for the left eye represents what the user is seeing - * at the moment with the users left eye. When this surface is created the - * DDSCAPS_PRIMARYSURFACE represents what the user is seeing with the users - * right eye. - */ -#define DDSCAPS_PRIMARYSURFACELEFT 0x00000400l - -/* - * Indicates that this surface memory was allocated in system memory - */ -#define DDSCAPS_SYSTEMMEMORY 0x00000800l - -/* - * Indicates that this surface can be used as a 3D texture. It does not - * indicate whether or not the surface is being used for that purpose. - */ -#define DDSCAPS_TEXTURE 0x00001000l - -/* - * Indicates that a surface may be a destination for 3D rendering. This - * bit must be set in order to query for a Direct3D Device Interface - * from this surface. - */ -#define DDSCAPS_3DDEVICE 0x00002000l - -/* - * Indicates that this surface exists in video memory. - */ -#define DDSCAPS_VIDEOMEMORY 0x00004000l - -/* - * Indicates that changes made to this surface are immediately visible. - * It is always set for the primary surface and is set for overlays while - * they are being overlayed and texture maps while they are being textured. - */ -#define DDSCAPS_VISIBLE 0x00008000l - -/* - * Indicates that only writes are permitted to the surface. Read accesses - * from the surface may or may not generate a protection fault, but the - * results of a read from this surface will not be meaningful. READ ONLY. - */ -#define DDSCAPS_WRITEONLY 0x00010000l - -/* - * Indicates that this surface is a z buffer. A z buffer does not contain - * displayable information. Instead it contains bit depth information that is - * used to determine which pixels are visible and which are obscured. - */ -#define DDSCAPS_ZBUFFER 0x00020000l - -/* - * Indicates surface will have a DC associated long term - */ -#define DDSCAPS_OWNDC 0x00040000l - -/* - * Indicates surface should be able to receive live video - */ -#define DDSCAPS_LIVEVIDEO 0x00080000l - -/* - * Indicates surface should be able to have a stream decompressed - * to it by the hardware. - */ -#define DDSCAPS_HWCODEC 0x00100000l - -/* - * Surface is a 320x200 or 320x240 ModeX surface - */ -#define DDSCAPS_MODEX 0x00200000l - -/* - * Indicates surface is one level of a mip-map. This surface will - * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map. - * This can be done explicitly, by creating a number of surfaces and - * attaching them with AddAttachedSurface or by implicitly by CreateSurface. - * If this bit is set then DDSCAPS_TEXTURE must also be set. - */ -#define DDSCAPS_MIPMAP 0x00400000l - - - -/* - * Indicates that memory for the surface is not allocated until the surface - * is loaded (via the Direct3D texture Load() function). - */ -#define DDSCAPS_ALLOCONLOAD 0x04000000l - - - - /**************************************************************************** - * - * DIRECTDRAW DRIVER CAPABILITY FLAGS - * - ****************************************************************************/ - -/* - * Display hardware has 3D acceleration. - */ -#define DDCAPS_3D 0x00000001l - -/* - * Indicates that DirectDraw will support only dest rectangles that are aligned - * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively. - * READ ONLY. - */ -#define DDCAPS_ALIGNBOUNDARYDEST 0x00000002l - -/* - * Indicates that DirectDraw will support only source rectangles whose sizes in - * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively. READ ONLY. - */ -#define DDCAPS_ALIGNSIZEDEST 0x00000004l -/* - * Indicates that DirectDraw will support only source rectangles that are aligned - * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively. - * READ ONLY. - */ -#define DDCAPS_ALIGNBOUNDARYSRC 0x00000008l - -/* - * Indicates that DirectDraw will support only source rectangles whose sizes in - * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively. READ ONLY. - */ -#define DDCAPS_ALIGNSIZESRC 0x00000010l - -/* - * Indicates that DirectDraw will create video memory surfaces that have a stride - * alignment equal to DIRECTDRAWCAPS.dwAlignStride. READ ONLY. - */ -#define DDCAPS_ALIGNSTRIDE 0x00000020l - -/* - * Display hardware is capable of blt operations. - */ -#define DDCAPS_BLT 0x00000040l - -/* - * Display hardware is capable of asynchronous blt operations. - */ -#define DDCAPS_BLTQUEUE 0x00000080l - -/* - * Display hardware is capable of color space conversions during the blt operation. - */ -#define DDCAPS_BLTFOURCC 0x00000100l - -/* - * Display hardware is capable of stretching during blt operations. - */ -#define DDCAPS_BLTSTRETCH 0x00000200l - -/* - * Display hardware is shared with GDI. - */ -#define DDCAPS_GDI 0x00000400l - -/* - * Display hardware can overlay. - */ -#define DDCAPS_OVERLAY 0x00000800l - -/* - * Set if display hardware supports overlays but can not clip them. - */ -#define DDCAPS_OVERLAYCANTCLIP 0x00001000l - -/* - * Indicates that overlay hardware is capable of color space conversions during - * the overlay operation. - */ -#define DDCAPS_OVERLAYFOURCC 0x00002000l - -/* - * Indicates that stretching can be done by the overlay hardware. - */ -#define DDCAPS_OVERLAYSTRETCH 0x00004000l - -/* - * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces - * other than the primary surface. - */ -#define DDCAPS_PALETTE 0x00008000l - -/* - * Indicates that palette changes can be syncd with the veritcal refresh. - */ -#define DDCAPS_PALETTEVSYNC 0x00010000l - -/* - * Display hardware can return the current scan line. - */ -#define DDCAPS_READSCANLINE 0x00020000l - -/* - * Display hardware has stereo vision capabilities. DDSCAPS_PRIMARYSURFACELEFT - * can be created. - */ -#define DDCAPS_STEREOVIEW 0x00040000l - -/* - * Display hardware is capable of generating a vertical blank interrupt. - */ -#define DDCAPS_VBI 0x00080000l - -/* - * Supports the use of z buffers with blt operations. - */ -#define DDCAPS_ZBLTS 0x00100000l - -/* - * Supports Z Ordering of overlays. - */ -#define DDCAPS_ZOVERLAYS 0x00200000l - -/* - * Supports color key - */ -#define DDCAPS_COLORKEY 0x00400000l - -/* - * Supports alpha surfaces - */ -#define DDCAPS_ALPHA 0x00800000l - -/* - * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set) - */ -#define DDCAPS_COLORKEYHWASSIST 0x01000000l - -/* - * no hardware support at all - */ -#define DDCAPS_NOHARDWARE 0x02000000l - -/* - * Display hardware is capable of color fill with bltter - */ -#define DDCAPS_BLTCOLORFILL 0x04000000l - -/* - * Display hardware is bank switched, and potentially very slow at - * random access to VRAM. - */ -#define DDCAPS_BANKSWITCHED 0x08000000l - -/* - * Display hardware is capable of depth filling Z-buffers with bltter - */ -#define DDCAPS_BLTDEPTHFILL 0x10000000l - -/* - * Display hardware is capable of clipping while bltting. - */ -#define DDCAPS_CANCLIP 0x20000000l - -/* - * Display hardware is capable of clipping while stretch bltting. - */ -#define DDCAPS_CANCLIPSTRETCHED 0x40000000l - -/* - * Display hardware is capable of bltting to or from system memory - */ -#define DDCAPS_CANBLTSYSMEM 0x80000000l - - - /**************************************************************************** - * - * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2) - * - ****************************************************************************/ - -/* - * Display hardware is certified - */ -#define DDCAPS2_CERTIFIED 0x00000001l - -/* - * Driver cannot interleave 2D operations (lock and blt) to surfaces with - * Direct3D rendering operations between calls to BeginScene() and EndScene() - */ -#define DDCAPS2_NO2DDURING3DSCENE 0x00000002l - -/**************************************************************************** - * - * DIRECTDRAW FX ALPHA CAPABILITY FLAGS - * - ****************************************************************************/ - -/* - * Supports alpha blending around the edge of a source color keyed surface. - * For Blt. - */ -#define DDFXALPHACAPS_BLTALPHAEDGEBLEND 0x00000001l - -/* - * Supports alpha information in the pixel format. The bit depth of alpha - * information in the pixel format can be 1,2,4, or 8. The alpha value becomes - * more opaque as the alpha value increases. (0 is transparent.) - * For Blt. - */ -#define DDFXALPHACAPS_BLTALPHAPIXELS 0x00000002l - -/* - * Supports alpha information in the pixel format. The bit depth of alpha - * information in the pixel format can be 1,2,4, or 8. The alpha value - * becomes more transparent as the alpha value increases. (0 is opaque.) - * This flag can only be set if DDCAPS_ALPHA is set. - * For Blt. - */ -#define DDFXALPHACAPS_BLTALPHAPIXELSNEG 0x00000004l - -/* - * Supports alpha only surfaces. The bit depth of an alpha only surface can be - * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. - * (0 is transparent.) - * For Blt. - */ -#define DDFXALPHACAPS_BLTALPHASURFACES 0x00000008l - -/* - * The depth of the alpha channel data can range can be 1,2,4, or 8. - * The NEG suffix indicates that this alpha channel becomes more transparent - * as the alpha value increases. (0 is opaque.) This flag can only be set if - * DDCAPS_ALPHA is set. - * For Blt. - */ -#define DDFXALPHACAPS_BLTALPHASURFACESNEG 0x00000010l - -/* - * Supports alpha blending around the edge of a source color keyed surface. - * For Overlays. - */ -#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND 0x00000020l - -/* - * Supports alpha information in the pixel format. The bit depth of alpha - * information in the pixel format can be 1,2,4, or 8. The alpha value becomes - * more opaque as the alpha value increases. (0 is transparent.) - * For Overlays. - */ -#define DDFXALPHACAPS_OVERLAYALPHAPIXELS 0x00000040l - -/* - * Supports alpha information in the pixel format. The bit depth of alpha - * information in the pixel format can be 1,2,4, or 8. The alpha value - * becomes more transparent as the alpha value increases. (0 is opaque.) - * This flag can only be set if DDCAPS_ALPHA is set. - * For Overlays. - */ -#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG 0x00000080l - -/* - * Supports alpha only surfaces. The bit depth of an alpha only surface can be - * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. - * (0 is transparent.) - * For Overlays. - */ -#define DDFXALPHACAPS_OVERLAYALPHASURFACES 0x00000100l - -/* - * The depth of the alpha channel data can range can be 1,2,4, or 8. - * The NEG suffix indicates that this alpha channel becomes more transparent - * as the alpha value increases. (0 is opaque.) This flag can only be set if - * DDCAPS_ALPHA is set. - * For Overlays. - */ -#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG 0x00000200l - -/**************************************************************************** - * - * DIRECTDRAW FX CAPABILITY FLAGS - * - ****************************************************************************/ - -/* - * Uses arithmetic operations to stretch and shrink surfaces during blt - * rather than pixel doubling techniques. Along the Y axis. - */ -#define DDFXCAPS_BLTARITHSTRETCHY 0x00000020l - -/* - * Uses arithmetic operations to stretch during blt - * rather than pixel doubling techniques. Along the Y axis. Only - * works for x1, x2, etc. - */ -#define DDFXCAPS_BLTARITHSTRETCHYN 0x00000010l - -/* - * Supports mirroring left to right in blt. - */ -#define DDFXCAPS_BLTMIRRORLEFTRIGHT 0x00000040l - -/* - * Supports mirroring top to bottom in blt. - */ -#define DDFXCAPS_BLTMIRRORUPDOWN 0x00000080l - -/* - * Supports arbitrary rotation for blts. - */ -#define DDFXCAPS_BLTROTATION 0x00000100l - -/* - * Supports 90 degree rotations for blts. - */ -#define DDFXCAPS_BLTROTATION90 0x00000200l - -/* - * DirectDraw supports arbitrary shrinking of a surface along the - * x axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSHRINKX 0x00000400l - -/* - * DirectDraw supports integer shrinking (1x,2x,) of a surface - * along the x axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSHRINKXN 0x00000800l - -/* - * DirectDraw supports arbitrary shrinking of a surface along the - * y axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSHRINKY 0x00001000l - -/* - * DirectDraw supports integer shrinking (1x,2x,) of a surface - * along the y axis (vertical direction) for blts. - */ -#define DDFXCAPS_BLTSHRINKYN 0x00002000l - -/* - * DirectDraw supports arbitrary stretching of a surface along the - * x axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSTRETCHX 0x00004000l - -/* - * DirectDraw supports integer stretching (1x,2x,) of a surface - * along the x axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSTRETCHXN 0x00008000l - -/* - * DirectDraw supports arbitrary stretching of a surface along the - * y axis (horizontal direction) for blts. - */ -#define DDFXCAPS_BLTSTRETCHY 0x00010000l - -/* - * DirectDraw supports integer stretching (1x,2x,) of a surface - * along the y axis (vertical direction) for blts. - */ -#define DDFXCAPS_BLTSTRETCHYN 0x00020000l - -/* - * Uses arithmetic operations to stretch and shrink surfaces during - * overlay rather than pixel doubling techniques. Along the Y axis - * for overlays. - */ -#define DDFXCAPS_OVERLAYARITHSTRETCHY 0x00040000l - -/* - * Uses arithmetic operations to stretch surfaces during - * overlay rather than pixel doubling techniques. Along the Y axis - * for overlays. Only works for x1, x2, etc. - */ -#define DDFXCAPS_OVERLAYARITHSTRETCHYN 0x00000008l - -/* - * DirectDraw supports arbitrary shrinking of a surface along the - * x axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSHRINKX 0x00080000l - -/* - * DirectDraw supports integer shrinking (1x,2x,) of a surface - * along the x axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSHRINKXN 0x00100000l - -/* - * DirectDraw supports arbitrary shrinking of a surface along the - * y axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSHRINKY 0x00200000l - -/* - * DirectDraw supports integer shrinking (1x,2x,) of a surface - * along the y axis (vertical direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSHRINKYN 0x00400000l - -/* - * DirectDraw supports arbitrary stretching of a surface along the - * x axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSTRETCHX 0x00800000l - -/* - * DirectDraw supports integer stretching (1x,2x,) of a surface - * along the x axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSTRETCHXN 0x01000000l - -/* - * DirectDraw supports arbitrary stretching of a surface along the - * y axis (horizontal direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSTRETCHY 0x02000000l - -/* - * DirectDraw supports integer stretching (1x,2x,) of a surface - * along the y axis (vertical direction) for overlays. - */ -#define DDFXCAPS_OVERLAYSTRETCHYN 0x04000000l - -/* - * DirectDraw supports mirroring of overlays across the vertical axis - */ -#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l - -/* - * DirectDraw supports mirroring of overlays across the horizontal axis - */ -#define DDFXCAPS_OVERLAYMIRRORUPDOWN 0x10000000l - -/**************************************************************************** - * - * DIRECTDRAW STEREO VIEW CAPABILITIES - * - ****************************************************************************/ - -/* - * The stereo view is accomplished via enigma encoding. - */ -#define DDSVCAPS_ENIGMA 0x00000001l - -/* - * The stereo view is accomplished via high frequency flickering. - */ -#define DDSVCAPS_FLICKER 0x00000002l - -/* - * The stereo view is accomplished via red and blue filters applied - * to the left and right eyes. All images must adapt their colorspaces - * for this process. - */ -#define DDSVCAPS_REDBLUE 0x00000004l - -/* - * The stereo view is accomplished with split screen technology. - */ -#define DDSVCAPS_SPLIT 0x00000008l - -/**************************************************************************** - * - * DIRECTDRAWPALETTE CAPABILITIES - * - ****************************************************************************/ - -/* - * Index is 4 bits. There are sixteen color entries in the palette table. - */ -#define DDPCAPS_4BIT 0x00000001l - -/* - * Index is onto a 8 bit color index. This field is only valid with the - * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target - * surface is in 8bpp. Each color entry is one byte long and is an index - * into destination surface's 8bpp palette. - */ -#define DDPCAPS_8BITENTRIES 0x00000002l - -/* - * Index is 8 bits. There are 256 color entries in the palette table. - */ -#define DDPCAPS_8BIT 0x00000004l - -/* - * Indicates that this DIRECTDRAWPALETTE should use the palette color array - * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE - * object. - */ -#define DDPCAPS_INITIALIZE 0x00000008l - -/* - * This palette is the one attached to the primary surface. Changing this - * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified - * and supported. - */ -#define DDPCAPS_PRIMARYSURFACE 0x00000010l - -/* - * This palette is the one attached to the primary surface left. Changing - * this table has immediate effect on the display for the left eye unless - * DDPSETPAL_VSYNC is specified and supported. - */ -#define DDPCAPS_PRIMARYSURFACELEFT 0x00000020l - -/* - * This palette can have all 256 entries defined - */ -#define DDPCAPS_ALLOW256 0x00000040l - -/* - * This palette can have modifications to it synced with the monitors - * refresh rate. - */ -#define DDPCAPS_VSYNC 0x00000080l - -/* - * Index is 1 bit. There are two color entries in the palette table. - */ -#define DDPCAPS_1BIT 0x00000100l - -/* - * Index is 2 bit. There are four color entries in the palette table. - */ -#define DDPCAPS_2BIT 0x00000200l - - -/**************************************************************************** - * - * DIRECTDRAWPALETTE SETENTRY CONSTANTS - * - ****************************************************************************/ - - -/**************************************************************************** - * - * DIRECTDRAWPALETTE GETENTRY CONSTANTS - * - ****************************************************************************/ - -/* 0 is the only legal value */ - -/**************************************************************************** - * - * DIRECTDRAWSURFACE SETPALETTE CONSTANTS - * - ****************************************************************************/ - - -/**************************************************************************** - * - * DIRECTDRAW BITDEPTH CONSTANTS - * - * NOTE: These are only used to indicate supported bit depths. These - * are flags only, they are not to be used as an actual bit depth. The - * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual - * bit depths in a surface or for changing the display mode. - * - ****************************************************************************/ - -/* - * 1 bit per pixel. - */ -#define DDBD_1 0x00004000l - -/* - * 2 bits per pixel. - */ -#define DDBD_2 0x00002000l - -/* - * 4 bits per pixel. - */ -#define DDBD_4 0x00001000l - -/* - * 8 bits per pixel. - */ -#define DDBD_8 0x00000800l - -/* - * 16 bits per pixel. - */ -#define DDBD_16 0x00000400l - -/* - * 24 bits per pixel. - */ -#define DDBD_24 0X00000200l - -/* - * 32 bits per pixel. - */ -#define DDBD_32 0x00000100l - -/**************************************************************************** - * - * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS - * - ****************************************************************************/ - -/* - * Set if the structure contains a color space. Not set if the structure - * contains a single color key. - */ -#define DDCKEY_COLORSPACE 0x00000001l - -/* - * Set if the structure specifies a color key or color space which is to be - * used as a destination color key for blt operations. - */ -#define DDCKEY_DESTBLT 0x00000002l - -/* - * Set if the structure specifies a color key or color space which is to be - * used as a destination color key for overlay operations. - */ -#define DDCKEY_DESTOVERLAY 0x00000004l - -/* - * Set if the structure specifies a color key or color space which is to be - * used as a source color key for blt operations. - */ -#define DDCKEY_SRCBLT 0x00000008l - -/* - * Set if the structure specifies a color key or color space which is to be - * used as a source color key for overlay operations. - */ -#define DDCKEY_SRCOVERLAY 0x00000010l - - -/**************************************************************************** - * - * DIRECTDRAW COLOR KEY CAPABILITY FLAGS - * - ****************************************************************************/ - -/* - * Supports transparent blting using a color key to identify the replaceable - * bits of the destination surface for RGB colors. - */ -#define DDCKEYCAPS_DESTBLT 0x00000001l - -/* - * Supports transparent blting using a color space to identify the replaceable - * bits of the destination surface for RGB colors. - */ -#define DDCKEYCAPS_DESTBLTCLRSPACE 0x00000002l - -/* - * Supports transparent blting using a color space to identify the replaceable - * bits of the destination surface for YUV colors. - */ -#define DDCKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004l - -/* - * Supports transparent blting using a color key to identify the replaceable - * bits of the destination surface for YUV colors. - */ -#define DDCKEYCAPS_DESTBLTYUV 0x00000008l - -/* - * Supports overlaying using colorkeying of the replaceable bits of the surface - * being overlayed for RGB colors. - */ -#define DDCKEYCAPS_DESTOVERLAY 0x00000010l - -/* - * Supports a color space as the color key for the destination for RGB colors. - */ -#define DDCKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020l - -/* - * Supports a color space as the color key for the destination for YUV colors. - */ -#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040l - -/* - * Supports only one active destination color key value for visible overlay - * surfaces. - */ -#define DDCKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080l - -/* - * Supports overlaying using colorkeying of the replaceable bits of the - * surface being overlayed for YUV colors. - */ -#define DDCKEYCAPS_DESTOVERLAYYUV 0x00000100l - -/* - * Supports transparent blting using the color key for the source with - * this surface for RGB colors. - */ -#define DDCKEYCAPS_SRCBLT 0x00000200l - -/* - * Supports transparent blting using a color space for the source with - * this surface for RGB colors. - */ -#define DDCKEYCAPS_SRCBLTCLRSPACE 0x00000400l - -/* - * Supports transparent blting using a color space for the source with - * this surface for YUV colors. - */ -#define DDCKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800l - -/* - * Supports transparent blting using the color key for the source with - * this surface for YUV colors. - */ -#define DDCKEYCAPS_SRCBLTYUV 0x00001000l - -/* - * Supports overlays using the color key for the source with this - * overlay surface for RGB colors. - */ -#define DDCKEYCAPS_SRCOVERLAY 0x00002000l - -/* - * Supports overlays using a color space as the source color key for - * the overlay surface for RGB colors. - */ -#define DDCKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000l - -/* - * Supports overlays using a color space as the source color key for - * the overlay surface for YUV colors. - */ -#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000l - -/* - * Supports only one active source color key value for visible - * overlay surfaces. - */ -#define DDCKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000l - -/* - * Supports overlays using the color key for the source with this - * overlay surface for YUV colors. - */ -#define DDCKEYCAPS_SRCOVERLAYYUV 0x00020000l - -/* - * there are no bandwidth trade-offs for using colorkey with an overlay - */ -#define DDCKEYCAPS_NOCOSTOVERLAY 0x00040000l - - -/**************************************************************************** - * - * DIRECTDRAW PIXELFORMAT FLAGS - * - ****************************************************************************/ - -/* - * The surface has alpha channel information in the pixel format. - */ -#define DDPF_ALPHAPIXELS 0x00000001l - -/* - * The pixel format contains alpha only information - */ -#define DDPF_ALPHA 0x00000002l - -/* - * The FourCC code is valid. - */ -#define DDPF_FOURCC 0x00000004l - -/* - * The surface is 4-bit color indexed. - */ -#define DDPF_PALETTEINDEXED4 0x00000008l - -/* - * The surface is indexed into a palette which stores indices - * into the destination surface's 8-bit palette. - */ -#define DDPF_PALETTEINDEXEDTO8 0x00000010l - -/* - * The surface is 8-bit color indexed. - */ -#define DDPF_PALETTEINDEXED8 0x00000020l - -/* - * The RGB data in the pixel format structure is valid. - */ -#define DDPF_RGB 0x00000040l - -/* - * The surface will accept pixel data in the format specified - * and compress it during the write. - */ -#define DDPF_COMPRESSED 0x00000080l - -/* - * The surface will accept RGB data and translate it during - * the write to YUV data. The format of the data to be written - * will be contained in the pixel format structure. The DDPF_RGB - * flag will be set. - */ -#define DDPF_RGBTOYUV 0x00000100l - -/* - * pixel format is YUV - YUV data in pixel format struct is valid - */ -#define DDPF_YUV 0x00000200l - -/* - * pixel format is a z buffer only surface - */ -#define DDPF_ZBUFFER 0x00000400l - -/* - * The surface is 1-bit color indexed. - */ -#define DDPF_PALETTEINDEXED1 0x00000800l - -/* - * The surface is 2-bit color indexed. - */ -#define DDPF_PALETTEINDEXED2 0x00001000l - -/*=========================================================================== - * - * - * DIRECTDRAW CALLBACK FLAGS - * - * - *==========================================================================*/ - -/**************************************************************************** - * - * DIRECTDRAW ENUMSURFACES FLAGS - * - ****************************************************************************/ - -/* - * Enumerate all of the surfaces that meet the search criterion. - */ -#define DDENUMSURFACES_ALL 0x00000001l - -/* - * A search hit is a surface that matches the surface description. - */ -#define DDENUMSURFACES_MATCH 0x00000002l - -/* - * A search hit is a surface that does not match the surface description. - */ -#define DDENUMSURFACES_NOMATCH 0x00000004l - -/* - * Enumerate the first surface that can be created which meets the search criterion. - */ -#define DDENUMSURFACES_CANBECREATED 0x00000008l - -/* - * Enumerate the surfaces that already exist that meet the search criterion. - */ -#define DDENUMSURFACES_DOESEXIST 0x00000010l - - -/**************************************************************************** - * - * DIRECTDRAW ENUMDISPLAYMODES FLAGS - * - ****************************************************************************/ - -/* - * Enumerate Modes with different refresh rates. EnumDisplayModes guarantees - * that a particular mode will be enumerated only once. This flag specifies whether - * the refresh rate is taken into account when determining if a mode is unique. - */ -#define DDEDM_REFRESHRATES 0x00000001l - - -/**************************************************************************** - * - * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS - * - ****************************************************************************/ - -/* - * Exclusive mode owner will be responsible for the entire primary surface. - * GDI can be ignored. used with DD - */ -#define DDSCL_FULLSCREEN 0x00000001l - -/* - * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode - */ -#define DDSCL_ALLOWREBOOT 0x00000002l - -/* - * prevents DDRAW from modifying the application window. - * prevents DDRAW from minimize/restore the application window on activation. - */ -#define DDSCL_NOWINDOWCHANGES 0x00000004l - -/* - * app wants to work as a regular Windows application - */ -#define DDSCL_NORMAL 0x00000008l - -/* - * app wants exclusive access - */ -#define DDSCL_EXCLUSIVE 0x00000010l - - -/* - * app can deal with non-windows display modes - */ -#define DDSCL_ALLOWMODEX 0x00000040l - - -/**************************************************************************** - * - * DIRECTDRAW BLT FLAGS - * - ****************************************************************************/ - -/* - * Use the alpha information in the pixel format or the alpha channel surface - * attached to the destination surface as the alpha channel for this blt. - */ -#define DDBLT_ALPHADEST 0x00000001l - -/* - * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel - * for the destination surface for this blt. - */ -#define DDBLT_ALPHADESTCONSTOVERRIDE 0x00000002l - -/* - * The NEG suffix indicates that the destination surface becomes more - * transparent as the alpha value increases. (0 is opaque) - */ -#define DDBLT_ALPHADESTNEG 0x00000004l - -/* - * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha - * channel for the destination for this blt. - */ -#define DDBLT_ALPHADESTSURFACEOVERRIDE 0x00000008l - -/* - * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel - * for the edges of the image that border the color key colors. - */ -#define DDBLT_ALPHAEDGEBLEND 0x00000010l - -/* - * Use the alpha information in the pixel format or the alpha channel surface - * attached to the source surface as the alpha channel for this blt. - */ -#define DDBLT_ALPHASRC 0x00000020l - -/* - * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel - * for the source for this blt. - */ -#define DDBLT_ALPHASRCCONSTOVERRIDE 0x00000040l - -/* - * The NEG suffix indicates that the source surface becomes more transparent - * as the alpha value increases. (0 is opaque) - */ -#define DDBLT_ALPHASRCNEG 0x00000080l - -/* - * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel - * for the source for this blt. - */ -#define DDBLT_ALPHASRCSURFACEOVERRIDE 0x00000100l - -/* - * Do this blt asynchronously through the FIFO in the order received. If - * there is no room in the hardware FIFO fail the call. - */ -#define DDBLT_ASYNC 0x00000200l - -/* - * Uses the dwFillColor field in the DDBLTFX structure as the RGB color - * to fill the destination rectangle on the destination surface with. - */ -#define DDBLT_COLORFILL 0x00000400l - -/* - * Uses the dwDDFX field in the DDBLTFX structure to specify the effects - * to use for the blt. - */ -#define DDBLT_DDFX 0x00000800l - -/* - * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS - * that are not part of the Win32 API. - */ -#define DDBLT_DDROPS 0x00001000l - -/* - * Use the color key associated with the destination surface. - */ -#define DDBLT_KEYDEST 0x00002000l - -/* - * Use the dckDestColorkey field in the DDBLTFX structure as the color key - * for the destination surface. - */ -#define DDBLT_KEYDESTOVERRIDE 0x00004000l - -/* - * Use the color key associated with the source surface. - */ -#define DDBLT_KEYSRC 0x00008000l - -/* - * Use the dckSrcColorkey field in the DDBLTFX structure as the color key - * for the source surface. - */ -#define DDBLT_KEYSRCOVERRIDE 0x00010000l - -/* - * Use the dwROP field in the DDBLTFX structure for the raster operation - * for this blt. These ROPs are the same as the ones defined in the Win32 API. - */ -#define DDBLT_ROP 0x00020000l - -/* - * Use the dwRotationAngle field in the DDBLTFX structure as the angle - * (specified in 1/100th of a degree) to rotate the surface. - */ -#define DDBLT_ROTATIONANGLE 0x00040000l - -/* - * Z-buffered blt using the z-buffers attached to the source and destination - * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the - * z-buffer opcode. - */ -#define DDBLT_ZBUFFER 0x00080000l - -/* - * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field - * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively - * for the destination. - */ -#define DDBLT_ZBUFFERDESTCONSTOVERRIDE 0x00100000l - -/* - * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode - * field in the DDBLTFX structure as the z-buffer and z-buffer opcode - * respectively for the destination. - */ -#define DDBLT_ZBUFFERDESTOVERRIDE 0x00200000l - -/* - * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field - * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively - * for the source. - */ -#define DDBLT_ZBUFFERSRCCONSTOVERRIDE 0x00400000l - -/* - * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode - * field in the DDBLTFX structure as the z-buffer and z-buffer opcode - * respectively for the source. - */ -#define DDBLT_ZBUFFERSRCOVERRIDE 0x00800000l - -/* - * wait until the device is ready to handle the blt - * this will cause blt to not return DDERR_WASSTILLDRAWING - */ -#define DDBLT_WAIT 0x01000000l - -/* - * Uses the dwFillDepth field in the DDBLTFX structure as the depth value - * to fill the destination rectangle on the destination Z-buffer surface - * with. - */ -#define DDBLT_DEPTHFILL 0x02000000l - - -/**************************************************************************** - * - * BLTFAST FLAGS - * - ****************************************************************************/ - -#define DDBLTFAST_NOCOLORKEY 0x00000000 -#define DDBLTFAST_SRCCOLORKEY 0x00000001 -#define DDBLTFAST_DESTCOLORKEY 0x00000002 -#define DDBLTFAST_WAIT 0x00000010 - -/**************************************************************************** - * - * FLIP FLAGS - * - ****************************************************************************/ - -#define DDFLIP_WAIT 0x00000001l - - -/**************************************************************************** - * - * DIRECTDRAW SURFACE OVERLAY FLAGS - * - ****************************************************************************/ - -/* - * Use the alpha information in the pixel format or the alpha channel surface - * attached to the destination surface as the alpha channel for the - * destination overlay. - */ -#define DDOVER_ALPHADEST 0x00000001l - -/* - * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the - * destination alpha channel for this overlay. - */ -#define DDOVER_ALPHADESTCONSTOVERRIDE 0x00000002l - -/* - * The NEG suffix indicates that the destination surface becomes more - * transparent as the alpha value increases. - */ -#define DDOVER_ALPHADESTNEG 0x00000004l - -/* - * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha - * channel destination for this overlay. - */ -#define DDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008l - -/* - * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha - * channel for the edges of the image that border the color key colors. - */ -#define DDOVER_ALPHAEDGEBLEND 0x00000010l - -/* - * Use the alpha information in the pixel format or the alpha channel surface - * attached to the source surface as the source alpha channel for this overlay. - */ -#define DDOVER_ALPHASRC 0x00000020l - -/* - * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source - * alpha channel for this overlay. - */ -#define DDOVER_ALPHASRCCONSTOVERRIDE 0x00000040l - -/* - * The NEG suffix indicates that the source surface becomes more transparent - * as the alpha value increases. - */ -#define DDOVER_ALPHASRCNEG 0x00000080l - -/* - * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel - * source for this overlay. - */ -#define DDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100l - -/* - * Turn this overlay off. - */ -#define DDOVER_HIDE 0x00000200l - -/* - * Use the color key associated with the destination surface. - */ -#define DDOVER_KEYDEST 0x00000400l - -/* - * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key - * for the destination surface - */ -#define DDOVER_KEYDESTOVERRIDE 0x00000800l - -/* - * Use the color key associated with the source surface. - */ -#define DDOVER_KEYSRC 0x00001000l - -/* - * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key - * for the source surface. - */ -#define DDOVER_KEYSRCOVERRIDE 0x00002000l - -/* - * Turn this overlay on. - */ -#define DDOVER_SHOW 0x00004000l - -/* - * Add a dirty rect to an emulated overlayed surface. - */ -#define DDOVER_ADDDIRTYRECT 0x00008000l - -/* - * Redraw all dirty rects on an emulated overlayed surface. - */ -#define DDOVER_REFRESHDIRTYRECTS 0x00010000l - -/* - * Redraw the entire surface on an emulated overlayed surface. - */ -#define DDOVER_REFRESHALL 0x00020000l - - -/* - * Use the overlay FX flags to define special overlay FX - */ -#define DDOVER_DDFX 0x00080000l - - -/**************************************************************************** - * - * DIRECTDRAWSURFACE LOCK FLAGS - * - ****************************************************************************/ - -/* - * The default. Set to indicate that Lock should return a valid memory pointer - * to the top of the specified rectangle. If no rectangle is specified then a - * pointer to the top of the surface is returned. - */ -#define DDLOCK_SURFACEMEMORYPTR 0x00000000L // default - -/* - * Set to indicate that Lock should wait until it can obtain a valid memory - * pointer before returning. If this bit is set, Lock will never return - * DDERR_WASSTILLDRAWING. - */ -#define DDLOCK_WAIT 0x00000001L - -/* - * Set if an event handle is being passed to Lock. Lock will trigger the event - * when it can return the surface memory pointer requested. - */ -#define DDLOCK_EVENT 0x00000002L - -/* - * Indicates that the surface being locked will only be read from. - */ -#define DDLOCK_READONLY 0x00000010L - -/* - * Indicates that the surface being locked will only be written to - */ -#define DDLOCK_WRITEONLY 0x00000020L - - -/**************************************************************************** - * - * DIRECTDRAWSURFACE PAGELOCK FLAGS - * - ****************************************************************************/ - -/* - * No flags defined at present - */ - - -/**************************************************************************** - * - * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS - * - ****************************************************************************/ - -/* - * No flags defined at present - */ - - -/**************************************************************************** - * - * DIRECTDRAWSURFACE BLT FX FLAGS - * - ****************************************************************************/ - -/* - * If stretching, use arithmetic stretching along the Y axis for this blt. - */ -#define DDBLTFX_ARITHSTRETCHY 0x00000001l - -/* - * Do this blt mirroring the surface left to right. Spin the - * surface around its y-axis. - */ -#define DDBLTFX_MIRRORLEFTRIGHT 0x00000002l - -/* - * Do this blt mirroring the surface up and down. Spin the surface - * around its x-axis. - */ -#define DDBLTFX_MIRRORUPDOWN 0x00000004l - -/* - * Schedule this blt to avoid tearing. - */ -#define DDBLTFX_NOTEARING 0x00000008l - -/* - * Do this blt rotating the surface one hundred and eighty degrees. - */ -#define DDBLTFX_ROTATE180 0x00000010l - -/* - * Do this blt rotating the surface two hundred and seventy degrees. - */ -#define DDBLTFX_ROTATE270 0x00000020l - -/* - * Do this blt rotating the surface ninety degrees. - */ -#define DDBLTFX_ROTATE90 0x00000040l - -/* - * Do this z blt using dwZBufferLow and dwZBufferHigh as range values - * specified to limit the bits copied from the source surface. - */ -#define DDBLTFX_ZBUFFERRANGE 0x00000080l - -/* - * Do this z blt adding the dwZBufferBaseDest to each of the sources z values - * before comparing it with the desting z values. - */ -#define DDBLTFX_ZBUFFERBASEDEST 0x00000100l - -/**************************************************************************** - * - * DIRECTDRAWSURFACE OVERLAY FX FLAGS - * - ****************************************************************************/ - -/* - * If stretching, use arithmetic stretching along the Y axis for this overlay. - */ -#define DDOVERFX_ARITHSTRETCHY 0x00000001l - -/* - * Mirror the overlay across the vertical axis - */ -#define DDOVERFX_MIRRORLEFTRIGHT 0x00000002l - -/* - * Mirror the overlay across the horizontal axis - */ -#define DDOVERFX_MIRRORUPDOWN 0x00000004l - -/**************************************************************************** - * - * DIRECTDRAW WAITFORVERTICALBLANK FLAGS - * - ****************************************************************************/ - -/* - * return when the vertical blank interval begins - */ -#define DDWAITVB_BLOCKBEGIN 0x00000001l - -/* - * set up an event to trigger when the vertical blank begins - */ -#define DDWAITVB_BLOCKBEGINEVENT 0x00000002l - -/* - * return when the vertical blank interval ends and display begins - */ -#define DDWAITVB_BLOCKEND 0x00000004l - -/**************************************************************************** - * - * DIRECTDRAW GETFLIPSTATUS FLAGS - * - ****************************************************************************/ - -/* - * is it OK to flip now? - */ -#define DDGFS_CANFLIP 0x00000001l - -/* - * is the last flip finished? - */ -#define DDGFS_ISFLIPDONE 0x00000002l - -/**************************************************************************** - * - * DIRECTDRAW GETBLTSTATUS FLAGS - * - ****************************************************************************/ - -/* - * is it OK to blt now? - */ -#define DDGBS_CANBLT 0x00000001l - -/* - * is the blt to the surface finished? - */ -#define DDGBS_ISBLTDONE 0x00000002l - - -/**************************************************************************** - * - * DIRECTDRAW ENUMOVERLAYZORDER FLAGS - * - ****************************************************************************/ - -/* - * Enumerate overlays back to front. - */ -#define DDENUMOVERLAYZ_BACKTOFRONT 0x00000000l - -/* - * Enumerate overlays front to back - */ -#define DDENUMOVERLAYZ_FRONTTOBACK 0x00000001l - -/**************************************************************************** - * - * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS - * - ****************************************************************************/ - -/* - * Send overlay to front - */ -#define DDOVERZ_SENDTOFRONT 0x00000000l - -/* - * Send overlay to back - */ -#define DDOVERZ_SENDTOBACK 0x00000001l - -/* - * Move Overlay forward - */ -#define DDOVERZ_MOVEFORWARD 0x00000002l - -/* - * Move Overlay backward - */ -#define DDOVERZ_MOVEBACKWARD 0x00000003l - -/* - * Move Overlay in front of relative surface - */ -#define DDOVERZ_INSERTINFRONTOF 0x00000004l - -/* - * Move Overlay in back of relative surface - */ -#define DDOVERZ_INSERTINBACKOF 0x00000005l - -/*=========================================================================== - * - * - * DIRECTDRAW RETURN CODES - * - * The return values from DirectDraw Commands and Surface that return an HRESULT - * are codes from DirectDraw concerning the results of the action - * requested by DirectDraw. - * - *==========================================================================*/ - -/* - * Status is OK - * - * Issued by: DirectDraw Commands and all callbacks - */ -#define DD_OK 0 - -/**************************************************************************** - * - * DIRECTDRAW ENUMCALLBACK RETURN VALUES - * - * EnumCallback returns are used to control the flow of the DIRECTDRAW and - * DIRECTDRAWSURFACE object enumerations. They can only be returned by - * enumeration callback routines. - * - ****************************************************************************/ - -/* - * stop the enumeration - */ -#define DDENUMRET_CANCEL 0 - -/* - * continue the enumeration - */ -#define DDENUMRET_OK 1 - -/**************************************************************************** - * - * DIRECTDRAW ERRORS - * - * Errors are represented by negative values and cannot be combined. - * - ****************************************************************************/ - -/* - * This object is already initialized - */ -#define DDERR_ALREADYINITIALIZED MAKE_DDHRESULT( 5 ) - -/* - * This surface can not be attached to the requested surface. - */ -#define DDERR_CANNOTATTACHSURFACE MAKE_DDHRESULT( 10 ) - -/* - * This surface can not be detached from the requested surface. - */ -#define DDERR_CANNOTDETACHSURFACE MAKE_DDHRESULT( 20 ) - -/* - * Support is currently not available. - */ -#define DDERR_CURRENTLYNOTAVAIL MAKE_DDHRESULT( 40 ) - -/* - * An exception was encountered while performing the requested operation - */ -#define DDERR_EXCEPTION MAKE_DDHRESULT( 55 ) - -/* - * Generic failure. - */ -#define DDERR_GENERIC E_FAIL - -/* - * Height of rectangle provided is not a multiple of reqd alignment - */ -#define DDERR_HEIGHTALIGN MAKE_DDHRESULT( 90 ) - -/* - * Unable to match primary surface creation request with existing - * primary surface. - */ -#define DDERR_INCOMPATIBLEPRIMARY MAKE_DDHRESULT( 95 ) - -/* - * One or more of the caps bits passed to the callback are incorrect. - */ -#define DDERR_INVALIDCAPS MAKE_DDHRESULT( 100 ) - -/* - * DirectDraw does not support provided Cliplist. - */ -#define DDERR_INVALIDCLIPLIST MAKE_DDHRESULT( 110 ) - -/* - * DirectDraw does not support the requested mode - */ -#define DDERR_INVALIDMODE MAKE_DDHRESULT( 120 ) - -/* - * DirectDraw received a pointer that was an invalid DIRECTDRAW object. - */ -#define DDERR_INVALIDOBJECT MAKE_DDHRESULT( 130 ) - -/* - * One or more of the parameters passed to the callback function are - * incorrect. - */ -#define DDERR_INVALIDPARAMS E_INVALIDARG - -/* - * pixel format was invalid as specified - */ -#define DDERR_INVALIDPIXELFORMAT MAKE_DDHRESULT( 145 ) - -/* - * Rectangle provided was invalid. - */ -#define DDERR_INVALIDRECT MAKE_DDHRESULT( 150 ) - -/* - * Operation could not be carried out because one or more surfaces are locked - */ -#define DDERR_LOCKEDSURFACES MAKE_DDHRESULT( 160 ) - -/* - * There is no 3D present. - */ -#define DDERR_NO3D MAKE_DDHRESULT( 170 ) - -/* - * Operation could not be carried out because there is no alpha accleration - * hardware present or available. - */ -#define DDERR_NOALPHAHW MAKE_DDHRESULT( 180 ) - - -/* - * no clip list available - */ -#define DDERR_NOCLIPLIST MAKE_DDHRESULT( 205 ) - -/* - * Operation could not be carried out because there is no color conversion - * hardware present or available. - */ -#define DDERR_NOCOLORCONVHW MAKE_DDHRESULT( 210 ) - -/* - * Create function called without DirectDraw object method SetCooperativeLevel - * being called. - */ -#define DDERR_NOCOOPERATIVELEVELSET MAKE_DDHRESULT( 212 ) - -/* - * Surface doesn't currently have a color key - */ -#define DDERR_NOCOLORKEY MAKE_DDHRESULT( 215 ) - -/* - * Operation could not be carried out because there is no hardware support - * of the dest color key. - */ -#define DDERR_NOCOLORKEYHW MAKE_DDHRESULT( 220 ) - -/* - * No DirectDraw support possible with current display driver - */ -#define DDERR_NODIRECTDRAWSUPPORT MAKE_DDHRESULT( 222 ) - -/* - * Operation requires the application to have exclusive mode but the - * application does not have exclusive mode. - */ -#define DDERR_NOEXCLUSIVEMODE MAKE_DDHRESULT( 225 ) - -/* - * Flipping visible surfaces is not supported. - */ -#define DDERR_NOFLIPHW MAKE_DDHRESULT( 230 ) - -/* - * There is no GDI present. - */ -#define DDERR_NOGDI MAKE_DDHRESULT( 240 ) - -/* - * Operation could not be carried out because there is no hardware present - * or available. - */ -#define DDERR_NOMIRRORHW MAKE_DDHRESULT( 250 ) - -/* - * Requested item was not found - */ -#define DDERR_NOTFOUND MAKE_DDHRESULT( 255 ) - -/* - * Operation could not be carried out because there is no overlay hardware - * present or available. - */ -#define DDERR_NOOVERLAYHW MAKE_DDHRESULT( 260 ) - -/* - * Operation could not be carried out because there is no appropriate raster - * op hardware present or available. - */ -#define DDERR_NORASTEROPHW MAKE_DDHRESULT( 280 ) - -/* - * Operation could not be carried out because there is no rotation hardware - * present or available. - */ -#define DDERR_NOROTATIONHW MAKE_DDHRESULT( 290 ) - -/* - * Operation could not be carried out because there is no hardware support - * for stretching - */ -#define DDERR_NOSTRETCHHW MAKE_DDHRESULT( 310 ) - -/* - * DirectDrawSurface is not in 4 bit color palette and the requested operation - * requires 4 bit color palette. - */ -#define DDERR_NOT4BITCOLOR MAKE_DDHRESULT( 316 ) - -/* - * DirectDrawSurface is not in 4 bit color index palette and the requested - * operation requires 4 bit color index palette. - */ -#define DDERR_NOT4BITCOLORINDEX MAKE_DDHRESULT( 317 ) - -/* - * DirectDraw Surface is not in 8 bit color mode and the requested operation - * requires 8 bit color. - */ -#define DDERR_NOT8BITCOLOR MAKE_DDHRESULT( 320 ) - -/* - * Operation could not be carried out because there is no texture mapping - * hardware present or available. - */ -#define DDERR_NOTEXTUREHW MAKE_DDHRESULT( 330 ) - -/* - * Operation could not be carried out because there is no hardware support - * for vertical blank synchronized operations. - */ -#define DDERR_NOVSYNCHW MAKE_DDHRESULT( 335 ) - -/* - * Operation could not be carried out because there is no hardware support - * for zbuffer blting. - */ -#define DDERR_NOZBUFFERHW MAKE_DDHRESULT( 340 ) - -/* - * Overlay surfaces could not be z layered based on their BltOrder because - * the hardware does not support z layering of overlays. - */ -#define DDERR_NOZOVERLAYHW MAKE_DDHRESULT( 350 ) - -/* - * The hardware needed for the requested operation has already been - * allocated. - */ -#define DDERR_OUTOFCAPS MAKE_DDHRESULT( 360 ) - -/* - * DirectDraw does not have enough memory to perform the operation. - */ -#define DDERR_OUTOFMEMORY E_OUTOFMEMORY - -/* - * DirectDraw does not have enough memory to perform the operation. - */ -#define DDERR_OUTOFVIDEOMEMORY MAKE_DDHRESULT( 380 ) - -/* - * hardware does not support clipped overlays - */ -#define DDERR_OVERLAYCANTCLIP MAKE_DDHRESULT( 382 ) - -/* - * Can only have ony color key active at one time for overlays - */ -#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE MAKE_DDHRESULT( 384 ) - -/* - * Access to this palette is being refused because the palette is already - * locked by another thread. - */ -#define DDERR_PALETTEBUSY MAKE_DDHRESULT( 387 ) - -/* - * No src color key specified for this operation. - */ -#define DDERR_COLORKEYNOTSET MAKE_DDHRESULT( 400 ) - -/* - * This surface is already attached to the surface it is being attached to. - */ -#define DDERR_SURFACEALREADYATTACHED MAKE_DDHRESULT( 410 ) - -/* - * This surface is already a dependency of the surface it is being made a - * dependency of. - */ -#define DDERR_SURFACEALREADYDEPENDENT MAKE_DDHRESULT( 420 ) - -/* - * Access to this surface is being refused because the surface is already - * locked by another thread. - */ -#define DDERR_SURFACEBUSY MAKE_DDHRESULT( 430 ) - -/* - * Access to this surface is being refused because no driver exists - * which can supply a pointer to the surface. - * This is most likely to happen when attempting to lock the primary - * surface when no DCI provider is present. - */ -#define DDERR_CANTLOCKSURFACE MAKE_DDHRESULT( 435 ) - -/* - * Access to Surface refused because Surface is obscured. - */ -#define DDERR_SURFACEISOBSCURED MAKE_DDHRESULT( 440 ) - -/* - * Access to this surface is being refused because the surface is gone. - * The DIRECTDRAWSURFACE object representing this surface should - * have Restore called on it. - */ -#define DDERR_SURFACELOST MAKE_DDHRESULT( 450 ) - -/* - * The requested surface is not attached. - */ -#define DDERR_SURFACENOTATTACHED MAKE_DDHRESULT( 460 ) - -/* - * Height requested by DirectDraw is too large. - */ -#define DDERR_TOOBIGHEIGHT MAKE_DDHRESULT( 470 ) - -/* - * Size requested by DirectDraw is too large -- The individual height and - * width are OK. - */ -#define DDERR_TOOBIGSIZE MAKE_DDHRESULT( 480 ) - -/* - * Width requested by DirectDraw is too large. - */ -#define DDERR_TOOBIGWIDTH MAKE_DDHRESULT( 490 ) - -/* - * Action not supported. - */ -#define DDERR_UNSUPPORTED E_NOTIMPL - -/* - * FOURCC format requested is unsupported by DirectDraw - */ -#define DDERR_UNSUPPORTEDFORMAT MAKE_DDHRESULT( 510 ) - -/* - * Bitmask in the pixel format requested is unsupported by DirectDraw - */ -#define DDERR_UNSUPPORTEDMASK MAKE_DDHRESULT( 520 ) - -/* - * vertical blank is in progress - */ -#define DDERR_VERTICALBLANKINPROGRESS MAKE_DDHRESULT( 537 ) - -/* - * Informs DirectDraw that the previous Blt which is transfering information - * to or from this Surface is incomplete. - */ -#define DDERR_WASSTILLDRAWING MAKE_DDHRESULT( 540 ) - -/* - * Rectangle provided was not horizontally aligned on reqd. boundary - */ -#define DDERR_XALIGN MAKE_DDHRESULT( 560 ) - -/* - * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver - * identifier. - */ -#define DDERR_INVALIDDIRECTDRAWGUID MAKE_DDHRESULT( 561 ) - -/* - * A DirectDraw object representing this driver has already been created - * for this process. - */ -#define DDERR_DIRECTDRAWALREADYCREATED MAKE_DDHRESULT( 562 ) - -/* - * A hardware only DirectDraw object creation was attempted but the driver - * did not support any hardware. - */ -#define DDERR_NODIRECTDRAWHW MAKE_DDHRESULT( 563 ) - -/* - * this process already has created a primary surface - */ -#define DDERR_PRIMARYSURFACEALREADYEXISTS MAKE_DDHRESULT( 564 ) - -/* - * software emulation not available. - */ -#define DDERR_NOEMULATION MAKE_DDHRESULT( 565 ) - -/* - * region passed to Clipper::GetClipList is too small. - */ -#define DDERR_REGIONTOOSMALL MAKE_DDHRESULT( 566 ) - -/* - * an attempt was made to set a clip list for a clipper objec that - * is already monitoring an hwnd. - */ -#define DDERR_CLIPPERISUSINGHWND MAKE_DDHRESULT( 567 ) - -/* - * No clipper object attached to surface object - */ -#define DDERR_NOCLIPPERATTACHED MAKE_DDHRESULT( 568 ) - -/* - * Clipper notification requires an HWND or - * no HWND has previously been set as the CooperativeLevel HWND. - */ -#define DDERR_NOHWND MAKE_DDHRESULT( 569 ) - -/* - * HWND used by DirectDraw CooperativeLevel has been subclassed, - * this prevents DirectDraw from restoring state. - */ -#define DDERR_HWNDSUBCLASSED MAKE_DDHRESULT( 570 ) - -/* - * The CooperativeLevel HWND has already been set. - * It can not be reset while the process has surfaces or palettes created. - */ -#define DDERR_HWNDALREADYSET MAKE_DDHRESULT( 571 ) - -/* - * No palette object attached to this surface. - */ -#define DDERR_NOPALETTEATTACHED MAKE_DDHRESULT( 572 ) - -/* - * No hardware support for 16 or 256 color palettes. - */ -#define DDERR_NOPALETTEHW MAKE_DDHRESULT( 573 ) - -/* - * If a clipper object is attached to the source surface passed into a - * BltFast call. - */ -#define DDERR_BLTFASTCANTCLIP MAKE_DDHRESULT( 574 ) - -/* - * No blter. - */ -#define DDERR_NOBLTHW MAKE_DDHRESULT( 575 ) - -/* - * No DirectDraw ROP hardware. - */ -#define DDERR_NODDROPSHW MAKE_DDHRESULT( 576 ) - -/* - * returned when GetOverlayPosition is called on a hidden overlay - */ -#define DDERR_OVERLAYNOTVISIBLE MAKE_DDHRESULT( 577 ) - -/* - * returned when GetOverlayPosition is called on a overlay that UpdateOverlay - * has never been called on to establish a destionation. - */ -#define DDERR_NOOVERLAYDEST MAKE_DDHRESULT( 578 ) - -/* - * returned when the position of the overlay on the destionation is no longer - * legal for that destionation. - */ -#define DDERR_INVALIDPOSITION MAKE_DDHRESULT( 579 ) - -/* - * returned when an overlay member is called for a non-overlay surface - */ -#define DDERR_NOTAOVERLAYSURFACE MAKE_DDHRESULT( 580 ) - -/* - * An attempt was made to set the cooperative level when it was already - * set to exclusive. - */ -#define DDERR_EXCLUSIVEMODEALREADYSET MAKE_DDHRESULT( 581 ) - -/* - * An attempt has been made to flip a surface that is not flippable. - */ -#define DDERR_NOTFLIPPABLE MAKE_DDHRESULT( 582 ) - -/* - * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly - * created. - */ -#define DDERR_CANTDUPLICATE MAKE_DDHRESULT( 583 ) - -/* - * Surface was not locked. An attempt to unlock a surface that was not - * locked at all, or by this process, has been attempted. - */ -#define DDERR_NOTLOCKED MAKE_DDHRESULT( 584 ) - -/* - * Windows can not create any more DCs - */ -#define DDERR_CANTCREATEDC MAKE_DDHRESULT( 585 ) - -/* - * No DC was ever created for this surface. - */ -#define DDERR_NODC MAKE_DDHRESULT( 586 ) - -/* - * This surface can not be restored because it was created in a different - * mode. - */ -#define DDERR_WRONGMODE MAKE_DDHRESULT( 587 ) - -/* - * This surface can not be restored because it is an implicitly created - * surface. - */ -#define DDERR_IMPLICITLYCREATED MAKE_DDHRESULT( 588 ) - -/* - * The surface being used is not a palette-based surface - */ -#define DDERR_NOTPALETTIZED MAKE_DDHRESULT( 589 ) - - -/* - * The display is currently in an unsupported mode - */ -#define DDERR_UNSUPPORTEDMODE MAKE_DDHRESULT( 590 ) - -/* - * Operation could not be carried out because there is no mip-map - * texture mapping hardware present or available. - */ -#define DDERR_NOMIPMAPHW MAKE_DDHRESULT( 591 ) - -/* - * The requested action could not be performed because the surface was of - * the wrong type. - */ -#define DDERR_INVALIDSURFACETYPE MAKE_DDHRESULT( 592 ) - - - -/* - * A DC has already been returned for this surface. Only one DC can be - * retrieved per surface. - */ -#define DDERR_DCALREADYCREATED MAKE_DDHRESULT( 620 ) - -/* - * The attempt to page lock a surface failed. - */ -#define DDERR_CANTPAGELOCK MAKE_DDHRESULT( 640 ) - -/* - * The attempt to page unlock a surface failed. - */ -#define DDERR_CANTPAGEUNLOCK MAKE_DDHRESULT( 660 ) - -/* - * An attempt was made to page unlock a surface with no outstanding page locks. - */ -#define DDERR_NOTPAGELOCKED MAKE_DDHRESULT( 680 ) - -/* - * An attempt was made to invoke an interface member of a DirectDraw object - * created by CoCreateInstance() before it was initialized. - */ -#define DDERR_NOTINITIALIZED CO_E_NOTINITIALIZED - -/* Alpha bit depth constants */ - - -#ifdef __cplusplus -}; -#endif - -#endif +/*==========================================================================; + * + * Copyright (C) 1994-1996 Microsoft Corporation. All Rights Reserved. + * + * File: ddraw.h + * Content: DirectDraw include file + * + ***************************************************************************/ + +#ifndef __DDRAW_INCLUDED__ +#define __DDRAW_INCLUDED__ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#define COM_NO_WINDOWS_H +#include +#else +#define IUnknown void +#define CO_E_NOTINITIALIZED 0x800401F0L +#endif + +#define _FACDD 0x876 +#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * GUIDS used by DirectDraw objects + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +DEFINE_GUID( CLSID_DirectDraw, 0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 ); +DEFINE_GUID( CLSID_DirectDrawClipper, 0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 ); +DEFINE_GUID( IID_IDirectDraw, 0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 ); +DEFINE_GUID( IID_IDirectDrawSurface, 0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 ); + +DEFINE_GUID( IID_IDirectDrawPalette, 0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDrawClipper, 0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); + +#endif + +/*============================================================================ + * + * DirectDraw Structures + * + * Various structures used to invoke DirectDraw. + * + *==========================================================================*/ + +struct IDirectDraw; +struct IDirectDrawSurface; +struct IDirectDrawPalette; +struct IDirectDrawClipper; + +typedef struct IDirectDraw FAR *LPDIRECTDRAW; +typedef struct IDirectDraw2 FAR *LPDIRECTDRAW2; +typedef struct IDirectDrawSurface FAR *LPDIRECTDRAWSURFACE; +typedef struct IDirectDrawSurface2 FAR *LPDIRECTDRAWSURFACE2; + +typedef struct IDirectDrawPalette FAR *LPDIRECTDRAWPALETTE; +typedef struct IDirectDrawClipper FAR *LPDIRECTDRAWCLIPPER; + +typedef struct _DDFXROP FAR *LPDDFXROP; +typedef struct _DDSURFACEDESC FAR *LPDDSURFACEDESC; + +/* + * API's + */ +#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM ) +//#if defined( _WIN32 ) && !defined( _NO_ENUM ) + typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID); + typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID); + extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext ); + extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext ); + #ifdef UNICODE + typedef LPDDENUMCALLBACKW LPDDENUMCALLBACK; + #define DirectDrawEnumerate DirectDrawEnumerateW + #else + typedef LPDDENUMCALLBACKA LPDDENUMCALLBACK; + #define DirectDrawEnumerate DirectDrawEnumerateA + #endif + extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); + extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter ); + #ifdef WINNT + //This is the user-mode entry stub to the kernel mode procedure. + extern HRESULT NtDirectDrawCreate( GUID FAR *lpGUID, HANDLE *lplpDD, IUnknown FAR *pUnkOuter ); + #endif +#endif + +#define REGSTR_KEY_DDHW_DESCRIPTION "Description" +#define REGSTR_KEY_DDHW_DRIVERNAME "DriverName" +#define REGSTR_PATH_DDHW "Hardware\\DirectDrawDrivers" + +#define DDCREATE_HARDWAREONLY 0x00000001l +#define DDCREATE_EMULATIONONLY 0x00000002l + +#ifdef WINNT +typedef long HRESULT; +#endif + +//#ifndef WINNT +typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID); +typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID); +//#endif +/* + * DDCOLORKEY + */ +typedef struct _DDCOLORKEY +{ + DWORD dwColorSpaceLowValue; // low boundary of color space that is to + // be treated as Color Key, inclusive + DWORD dwColorSpaceHighValue; // high boundary of color space that is + // to be treated as Color Key, inclusive +} DDCOLORKEY; + +typedef DDCOLORKEY FAR* LPDDCOLORKEY; + +/* + * DDBLTFX + * Used to pass override information to the DIRECTDRAWSURFACE callback Blt. + */ +typedef struct _DDBLTFX +{ + DWORD dwSize; // size of structure + DWORD dwDDFX; // FX operations + DWORD dwROP; // Win32 raster operations + DWORD dwDDROP; // Raster operations new for DirectDraw + DWORD dwRotationAngle; // Rotation angle for blt + DWORD dwZBufferOpCode; // ZBuffer compares + DWORD dwZBufferLow; // Low limit of Z buffer + DWORD dwZBufferHigh; // High limit of Z buffer + DWORD dwZBufferBaseDest; // Destination base value + DWORD dwZDestConstBitDepth; // Bit depth used to specify Z constant for destination + union + { + DWORD dwZDestConst; // Constant to use as Z buffer for dest + LPDIRECTDRAWSURFACE lpDDSZBufferDest; // Surface to use as Z buffer for dest + }; + DWORD dwZSrcConstBitDepth; // Bit depth used to specify Z constant for source + union + { + DWORD dwZSrcConst; // Constant to use as Z buffer for src + LPDIRECTDRAWSURFACE lpDDSZBufferSrc; // Surface to use as Z buffer for src + }; + DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend + DWORD dwAlphaEdgeBlend; // Alpha for edge blending + DWORD dwReserved; + DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination + union + { + DWORD dwAlphaDestConst; // Constant to use as Alpha Channel + LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as Alpha Channel + }; + DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source + union + { + DWORD dwAlphaSrcConst; // Constant to use as Alpha Channel + LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as Alpha Channel + }; + union + { + DWORD dwFillColor; // color in RGB or Palettized + DWORD dwFillDepth; // depth value for z-buffer + LPDIRECTDRAWSURFACE lpDDSPattern; // Surface to use as pattern + }; + DDCOLORKEY ddckDestColorkey; // DestColorkey override + DDCOLORKEY ddckSrcColorkey; // SrcColorkey override +} DDBLTFX; + +typedef DDBLTFX FAR* LPDDBLTFX; + + +/* + * DDSCAPS + */ +typedef struct _DDSCAPS +{ + DWORD dwCaps; // capabilities of surface wanted +} DDSCAPS; + +typedef DDSCAPS FAR* LPDDSCAPS; + +/* + * DDCAPS + */ +#define DD_ROP_SPACE (256/32) // space required to store ROP array + +typedef struct _DDCAPS +{ + DWORD dwSize; // size of the DDDRIVERCAPS structure + DWORD dwCaps; // driver specific capabilities + DWORD dwCaps2; // more driver specific capabilites + DWORD dwCKeyCaps; // color key capabilities of the surface + DWORD dwFXCaps; // driver specific stretching and effects capabilites + DWORD dwFXAlphaCaps; // alpha driver specific capabilities + DWORD dwPalCaps; // palette capabilities + DWORD dwSVCaps; // stereo vision capabilities + DWORD dwAlphaBltConstBitDepths; // DDBD_2,4,8 + DWORD dwAlphaBltPixelBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaBltSurfaceBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaOverlayConstBitDepths; // DDBD_2,4,8 + DWORD dwAlphaOverlayPixelBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8 + DWORD dwZBufferBitDepths; // DDBD_8,16,24,32 + DWORD dwVidMemTotal; // total amount of video memory + DWORD dwVidMemFree; // amount of free video memory + DWORD dwMaxVisibleOverlays; // maximum number of visible overlays + DWORD dwCurrVisibleOverlays; // current number of visible overlays + DWORD dwNumFourCCCodes; // number of four cc codes + DWORD dwAlignBoundarySrc; // source rectangle alignment + DWORD dwAlignSizeSrc; // source rectangle byte size + DWORD dwAlignBoundaryDest; // dest rectangle alignment + DWORD dwAlignSizeDest; // dest rectangle byte size + DWORD dwAlignStrideAlign; // stride alignment + DWORD dwRops[DD_ROP_SPACE]; // ROPS supported + DDSCAPS ddsCaps; // DDSCAPS structure has all the general capabilities + DWORD dwMinOverlayStretch; // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxOverlayStretch; // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMinLiveVideoStretch; // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxLiveVideoStretch; // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMinHwCodecStretch; // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxHwCodecStretch; // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwReserved1; // reserved + DWORD dwReserved2; // reserved + DWORD dwReserved3; // reserved + DWORD dwSVBCaps; // driver specific capabilities for System->Vmem blts + DWORD dwSVBCKeyCaps; // driver color key capabilities for System->Vmem blts + DWORD dwSVBFXCaps; // driver FX capabilities for System->Vmem blts + DWORD dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts + DWORD dwVSBCaps; // driver specific capabilities for Vmem->System blts + DWORD dwVSBCKeyCaps; // driver color key capabilities for Vmem->System blts + DWORD dwVSBFXCaps; // driver FX capabilities for Vmem->System blts + DWORD dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts + DWORD dwSSBCaps; // driver specific capabilities for System->System blts + DWORD dwSSBCKeyCaps; // driver color key capabilities for System->System blts + DWORD dwSSBFXCaps; // driver FX capabilities for System->System blts + DWORD dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts + DWORD dwReserved4; // reserved + DWORD dwReserved5; // reserved + DWORD dwReserved6; // reserved +} DDCAPS; + +typedef DDCAPS FAR* LPDDCAPS; + + + +/* + * DDPIXELFORMAT + */ +typedef struct _DDPIXELFORMAT +{ + DWORD dwSize; // size of structure + DWORD dwFlags; // pixel format flags + DWORD dwFourCC; // (FOURCC code) + union + { + DWORD dwRGBBitCount; // how many bits per pixel (BD_4,8,16,24,32) + DWORD dwYUVBitCount; // how many bits per pixel (BD_4,8,16,24,32) + DWORD dwZBufferBitDepth; // how many bits for z buffers (BD_8,16,24,32) + DWORD dwAlphaBitDepth; // how many bits for alpha channels (BD_1,2,4,8) + }; + union + { + DWORD dwRBitMask; // mask for red bit + DWORD dwYBitMask; // mask for Y bits + }; + union + { + DWORD dwGBitMask; // mask for green bits + DWORD dwUBitMask; // mask for U bits + }; + union + { + DWORD dwBBitMask; // mask for blue bits + DWORD dwVBitMask; // mask for V bits + }; + union + { + DWORD dwRGBAlphaBitMask; // mask for alpha channel + DWORD dwYUVAlphaBitMask; // mask for alpha channel + }; +} DDPIXELFORMAT; + +typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT; + +/* + * DDOVERLAYFX + */ +typedef struct _DDOVERLAYFX +{ + DWORD dwSize; // size of structure + DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend + DWORD dwAlphaEdgeBlend; // Constant to use as alpha for edge blend + DWORD dwReserved; + DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination + union + { + DWORD dwAlphaDestConst; // Constant to use as alpha channel for dest + LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as alpha channel for dest + }; + DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source + union + { + DWORD dwAlphaSrcConst; // Constant to use as alpha channel for src + LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as alpha channel for src + }; + DDCOLORKEY dckDestColorkey; // DestColorkey override + DDCOLORKEY dckSrcColorkey; // DestColorkey override + DWORD dwDDFX; // Overlay FX + DWORD dwFlags; // flags +} DDOVERLAYFX; + +typedef DDOVERLAYFX FAR *LPDDOVERLAYFX; + +/* + * DDBLTBATCH: BltBatch entry structure + */ +typedef struct _DDBLTBATCH +{ + LPRECT lprDest; + LPDIRECTDRAWSURFACE lpDDSSrc; + LPRECT lprSrc; + DWORD dwFlags; + LPDDBLTFX lpDDBltFx; +} DDBLTBATCH; + +typedef DDBLTBATCH FAR * LPDDBLTBATCH; + +/* + * callbacks + */ +typedef DWORD (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext ); +#ifdef STREAMING +typedef DWORD (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD); +#endif + + +/* + * INTERACES FOLLOW: + * IDirectDraw + * IDirectDrawClipper + * IDirectDrawPalette + * IDirectDrawSurface + */ + +/* + * IDirectDraw + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDraw +DECLARE_INTERFACE_( IDirectDraw, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDraw methods ***/ + STDMETHOD(Compact)(THIS) PURE; + STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; + STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; + STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; + STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; + STDMETHOD(FlipToGDISurface)(THIS) PURE; + STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; + STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; + STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; + STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; + STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; + STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; + STDMETHOD(RestoreDisplayMode)(THIS) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; + STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE; + STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDraw_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDraw_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDraw_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDraw_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectDraw_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) +#define IDirectDraw_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) +#define IDirectDraw_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) +#define IDirectDraw_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) +#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) +#define IDirectDraw_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) +#define IDirectDraw_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) +#define IDirectDraw_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) +#define IDirectDraw_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) +#define IDirectDraw_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) +#define IDirectDraw_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) +#define IDirectDraw_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) +#define IDirectDraw_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) +#define IDirectDraw_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) +#define IDirectDraw_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirectDraw_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) +#define IDirectDraw_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) +#define IDirectDraw_SetDisplayMode(p, a, b, c) (p)->lpVtbl->SetDisplayMode(p, a, b, c) +#define IDirectDraw_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) +#endif + +#endif + +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDraw2 +DECLARE_INTERFACE_( IDirectDraw2, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDraw methods ***/ + STDMETHOD(Compact)(THIS) PURE; + STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; + STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; + STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; + STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; + STDMETHOD(FlipToGDISurface)(THIS) PURE; + STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; + STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; + STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; + STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; + STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; + STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; + STDMETHOD(RestoreDisplayMode)(THIS) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; + STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE; + STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; + /*** Added in the v2 interface ***/ + STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE; +}; +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDraw2_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDraw2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDraw2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDraw2_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectDraw2_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) +#define IDirectDraw2_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) +#define IDirectDraw2_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) +#define IDirectDraw2_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) +#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) +#define IDirectDraw2_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) +#define IDirectDraw2_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) +#define IDirectDraw2_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) +#define IDirectDraw2_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) +#define IDirectDraw2_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) +#define IDirectDraw2_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) +#define IDirectDraw2_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) +#define IDirectDraw2_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) +#define IDirectDraw2_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) +#define IDirectDraw2_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirectDraw2_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) +#define IDirectDraw2_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) +#define IDirectDraw2_SetDisplayMode(p, a, b, c, d) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d) +#define IDirectDraw2_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) +#define IDirectDraw2_GetAvailableVidMem(p, a, b, c) (p)->lpVtbl->GetAvailableVidMem(p, a, b, c) +#endif + +#endif + +/* + * IDirectDrawPalette + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawPalette +DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawPalette methods ***/ + STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE; + STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE; + STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawPalette_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDrawPalette_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawPalette_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawPalette_GetCaps(p, a) (p)->lpVtbl->GetCaps(p, a) +#define IDirectDrawPalette_GetEntries(p, a, b, c, d) (p)->lpVtbl->GetEntries(p, a, b, c, d) +#define IDirectDrawPalette_Initialize(p, a, b, c) (p)->lpVtbl->Initialize(p, a, b, c) +#define IDirectDrawPalette_SetEntries(p, a, b, c, d) (p)->lpVtbl->SetEntries(p, a, b, c, d) +#endif + +#endif + +/* + * IDirectDrawClipper + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawClipper +DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawClipper methods ***/ + STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE; + STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE; + STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE; + STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE; + STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawClipper_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDrawClipper_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawClipper_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawClipper_GetClipList(p, a, b, c) (p)->lpVtbl->GetClipList(p, a, b, c) +#define IDirectDrawClipper_GetHWnd(p, a) (p)->lpVtbl->GetHWnd(p, a) +#define IDirectDrawClipper_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) +#define IDirectDrawClipper_IsClipListChanged(p, a) (p)->lpVtbl->IsClipListChanged(p, a) +#define IDirectDrawClipper_SetClipList(p, a, b) (p)->lpVtbl->SetClipList(p, a, b) +#define IDirectDrawClipper_SetHWnd(p, a, b) (p)->lpVtbl->SetHWnd(p, a, b) +#endif + +#endif + +/* + * IDirectDrawSurface and related interfaces + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawSurface +DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawSurface methods ***/ + STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; + STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE; + STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; + STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE; + STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE; + STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; + STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; + STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; + STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; + STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; + STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; + STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; + STDMETHOD(IsLost)(THIS) PURE; + STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; + STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; + STDMETHOD(Restore)(THIS) PURE; + STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; + STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; + STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; + STDMETHOD(Unlock)(THIS_ LPVOID) PURE; + STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE; + STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; + STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawSurface_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectDrawSurface_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawSurface_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawSurface_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) +#define IDirectDrawSurface_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) +#define IDirectDrawSurface_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) +#define IDirectDrawSurface_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) +#define IDirectDrawSurface_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) +#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) +#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) +#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) +#define IDirectDrawSurface_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) +#define IDirectDrawSurface_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) +#define IDirectDrawSurface_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) +#define IDirectDrawSurface_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) +#define IDirectDrawSurface_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) +#define IDirectDrawSurface_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) +#define IDirectDrawSurface_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) +#define IDirectDrawSurface_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) +#define IDirectDrawSurface_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) +#define IDirectDrawSurface_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) +#define IDirectDrawSurface_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) +#define IDirectDrawSurface_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) +#define IDirectDrawSurface_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectDrawSurface_IsLost(p) (p)->lpVtbl->IsLost(p) +#define IDirectDrawSurface_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirectDrawSurface_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) +#define IDirectDrawSurface_Restore(p) (p)->lpVtbl->Restore(p) +#define IDirectDrawSurface_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) +#define IDirectDrawSurface_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) +#define IDirectDrawSurface_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) +#define IDirectDrawSurface_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) +#define IDirectDrawSurface_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) +#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) +#define IDirectDrawSurface_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) +#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) +#endif + +/* + * IDirectDrawSurface2 and related interfaces + */ +#undef INTERFACE +#define INTERFACE IDirectDrawSurface2 +DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawSurface methods ***/ + STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE; + STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; + STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE; + STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; + STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE; + STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE; + STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE; + STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE; + STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; + STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; + STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; + STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; + STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; + STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; + STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; + STDMETHOD(IsLost)(THIS) PURE; + STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; + STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; + STDMETHOD(Restore)(THIS) PURE; + STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; + STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; + STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; + STDMETHOD(Unlock)(THIS_ LPVOID) PURE; + STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE; + STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; + STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE; + /*** Added in the v2 interface ***/ + STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE; + STDMETHOD(PageLock)(THIS_ DWORD) PURE; + STDMETHOD(PageUnlock)(THIS_ DWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawSurface2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectDrawSurface2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawSurface2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawSurface2_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) +#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) +#define IDirectDrawSurface2_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) +#define IDirectDrawSurface2_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) +#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) +#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) +#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) +#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) +#define IDirectDrawSurface2_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) +#define IDirectDrawSurface2_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) +#define IDirectDrawSurface2_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) +#define IDirectDrawSurface2_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) +#define IDirectDrawSurface2_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) +#define IDirectDrawSurface2_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) +#define IDirectDrawSurface2_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) +#define IDirectDrawSurface2_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) +#define IDirectDrawSurface2_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) +#define IDirectDrawSurface2_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) +#define IDirectDrawSurface2_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) +#define IDirectDrawSurface2_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) +#define IDirectDrawSurface2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectDrawSurface2_IsLost(p) (p)->lpVtbl->IsLost(p) +#define IDirectDrawSurface2_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirectDrawSurface2_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) +#define IDirectDrawSurface2_Restore(p) (p)->lpVtbl->Restore(p) +#define IDirectDrawSurface2_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) +#define IDirectDrawSurface2_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) +#define IDirectDrawSurface2_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) +#define IDirectDrawSurface2_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) +#define IDirectDrawSurface2_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) +#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) +#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) +#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) +#define IDirectDrawSurface2_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) +#define IDirectDrawSurface2_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) +#define IDirectDrawSurface2_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) +#endif + + +#endif + + +/* + * DDSURFACEDESC + */ +typedef struct _DDSURFACEDESC +{ + DWORD dwSize; // size of the DDSURFACEDESC structure + DWORD dwFlags; // determines what fields are valid + DWORD dwHeight; // height of surface to be created + DWORD dwWidth; // width of input surface + LONG lPitch; // distance to start of next line (return value only) + DWORD dwBackBufferCount; // number of back buffers requested + union + { + DWORD dwMipMapCount; // number of mip-map levels requested + DWORD dwZBufferBitDepth; // depth of Z buffer requested + DWORD dwRefreshRate; // refresh rate (used when display mode is described) + }; + DWORD dwAlphaBitDepth; // depth of alpha buffer requested + DWORD dwReserved; // reserved + LPVOID lpSurface; // pointer to the associated surface memory + DDCOLORKEY ddckCKDestOverlay; // color key for destination overlay use + DDCOLORKEY ddckCKDestBlt; // color key for destination blt use + DDCOLORKEY ddckCKSrcOverlay; // color key for source overlay use + DDCOLORKEY ddckCKSrcBlt; // color key for source blt use + DDPIXELFORMAT ddpfPixelFormat; // pixel format description of the surface + DDSCAPS ddsCaps; // direct draw surface capabilities +} DDSURFACEDESC; + +/* + * ddsCaps field is valid. + */ +#define DDSD_CAPS 0x00000001l // default + +/* + * dwHeight field is valid. + */ +#define DDSD_HEIGHT 0x00000002l + +/* + * dwWidth field is valid. + */ +#define DDSD_WIDTH 0x00000004l + +/* + * lPitch is valid. + */ +#define DDSD_PITCH 0x00000008l + +/* + * dwBackBufferCount is valid. + */ +#define DDSD_BACKBUFFERCOUNT 0x00000020l + +/* + * dwZBufferBitDepth is valid. + */ +#define DDSD_ZBUFFERBITDEPTH 0x00000040l + +/* + * dwAlphaBitDepth is valid. + */ +#define DDSD_ALPHABITDEPTH 0x00000080l + + + +/* + * ddpfPixelFormat is valid. + */ +#define DDSD_PIXELFORMAT 0x00001000l + +/* + * ddckCKDestOverlay is valid. + */ +#define DDSD_CKDESTOVERLAY 0x00002000l + +/* + * ddckCKDestBlt is valid. + */ +#define DDSD_CKDESTBLT 0x00004000l + +/* + * ddckCKSrcOverlay is valid. + */ +#define DDSD_CKSRCOVERLAY 0x00008000l + +/* + * ddckCKSrcBlt is valid. + */ +#define DDSD_CKSRCBLT 0x00010000l + +/* + * dwMipMapCount is valid. + */ +#define DDSD_MIPMAPCOUNT 0x00020000l + + /* + * dwRefreshRate is valid + */ +#define DDSD_REFRESHRATE 0x00040000l + + +/* + * All input fields are valid. + */ +#define DDSD_ALL 0x0007f9eel + + +/*============================================================================ + * + * Direct Draw Capability Flags + * + * These flags are used to describe the capabilities of a given Surface. + * All flags are bit flags. + * + *==========================================================================*/ + +/**************************************************************************** + * + * DIRECTDRAWSURFACE CAPABILITY FLAGS + * + ****************************************************************************/ +/* + * This bit currently has no meaning. + */ +#define DDSCAPS_3D 0x00000001l + +/* + * Indicates that this surface contains alpha information. The pixel + * format must be interrogated to determine whether this surface + * contains only alpha information or alpha information interlaced + * with pixel color data (e.g. RGBA or YUVA). + */ +#define DDSCAPS_ALPHA 0x00000002l + +/* + * Indicates that this surface is a backbuffer. It is generally + * set by CreateSurface when the DDSCAPS_FLIP capability bit is set. + * It indicates that this surface is THE back buffer of a surface + * flipping structure. DirectDraw supports N surfaces in a + * surface flipping structure. Only the surface that immediately + * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set. + * The other surfaces are identified as back buffers by the presence + * of the DDSCAPS_FLIP capability, their attachment order, and the + * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER + * capabilities. The bit is sent to CreateSurface when a standalone + * back buffer is being created. This surface could be attached to + * a front buffer and/or back buffers to form a flipping surface + * structure after the CreateSurface call. See AddAttachments for + * a detailed description of the behaviors in this case. + */ +#define DDSCAPS_BACKBUFFER 0x00000004l + +/* + * Indicates a complex surface structure is being described. A + * complex surface structure results in the creation of more than + * one surface. The additional surfaces are attached to the root + * surface. The complex structure can only be destroyed by + * destroying the root. + */ +#define DDSCAPS_COMPLEX 0x00000008l + +/* + * Indicates that this surface is a part of a surface flipping structure. + * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and + * DDSCAP_BACKBUFFER bits are not set. They are set by CreateSurface + * on the resulting creations. The dwBackBufferCount field in the + * DDSURFACEDESC structure must be set to at least 1 in order for + * the CreateSurface call to succeed. The DDSCAPS_COMPLEX capability + * must always be set with creating multiple surfaces through CreateSurface. + */ +#define DDSCAPS_FLIP 0x00000010l + +/* + * Indicates that this surface is THE front buffer of a surface flipping + * structure. It is generally set by CreateSurface when the DDSCAPS_FLIP + * capability bit is set. + * If this capability is sent to CreateSurface then a standalonw front buffer + * is created. This surface will not have the DDSCAPS_FLIP capability. + * It can be attached to other back buffers to form a flipping structure. + * See AddAttachments for a detailed description of the behaviors in this + * case. + */ +#define DDSCAPS_FRONTBUFFER 0x00000020l + +/* + * Indicates that this surface is any offscreen surface that is not an overlay, + * texture, zbuffer, front buffer, back buffer, or alpha surface. It is used + * to identify plain vanilla surfaces. + */ +#define DDSCAPS_OFFSCREENPLAIN 0x00000040l + +/* + * Indicates that this surface is an overlay. It may or may not be directly visible + * depending on whether or not it is currently being overlayed onto the primary + * surface. DDSCAPS_VISIBLE can be used to determine whether or not it is being + * overlayed at the moment. + */ +#define DDSCAPS_OVERLAY 0x00000080l + +/* + * Indicates that unique DirectDrawPalette objects can be created and + * attached to this surface. + */ +#define DDSCAPS_PALETTE 0x00000100l + +/* + * Indicates that this surface is the primary surface. The primary + * surface represents what the user is seeing at the moment. + */ +#define DDSCAPS_PRIMARYSURFACE 0x00000200l + +/* + * Indicates that this surface is the primary surface for the left eye. + * The primary surface for the left eye represents what the user is seeing + * at the moment with the users left eye. When this surface is created the + * DDSCAPS_PRIMARYSURFACE represents what the user is seeing with the users + * right eye. + */ +#define DDSCAPS_PRIMARYSURFACELEFT 0x00000400l + +/* + * Indicates that this surface memory was allocated in system memory + */ +#define DDSCAPS_SYSTEMMEMORY 0x00000800l + +/* + * Indicates that this surface can be used as a 3D texture. It does not + * indicate whether or not the surface is being used for that purpose. + */ +#define DDSCAPS_TEXTURE 0x00001000l + +/* + * Indicates that a surface may be a destination for 3D rendering. This + * bit must be set in order to query for a Direct3D Device Interface + * from this surface. + */ +#define DDSCAPS_3DDEVICE 0x00002000l + +/* + * Indicates that this surface exists in video memory. + */ +#define DDSCAPS_VIDEOMEMORY 0x00004000l + +/* + * Indicates that changes made to this surface are immediately visible. + * It is always set for the primary surface and is set for overlays while + * they are being overlayed and texture maps while they are being textured. + */ +#define DDSCAPS_VISIBLE 0x00008000l + +/* + * Indicates that only writes are permitted to the surface. Read accesses + * from the surface may or may not generate a protection fault, but the + * results of a read from this surface will not be meaningful. READ ONLY. + */ +#define DDSCAPS_WRITEONLY 0x00010000l + +/* + * Indicates that this surface is a z buffer. A z buffer does not contain + * displayable information. Instead it contains bit depth information that is + * used to determine which pixels are visible and which are obscured. + */ +#define DDSCAPS_ZBUFFER 0x00020000l + +/* + * Indicates surface will have a DC associated long term + */ +#define DDSCAPS_OWNDC 0x00040000l + +/* + * Indicates surface should be able to receive live video + */ +#define DDSCAPS_LIVEVIDEO 0x00080000l + +/* + * Indicates surface should be able to have a stream decompressed + * to it by the hardware. + */ +#define DDSCAPS_HWCODEC 0x00100000l + +/* + * Surface is a 320x200 or 320x240 ModeX surface + */ +#define DDSCAPS_MODEX 0x00200000l + +/* + * Indicates surface is one level of a mip-map. This surface will + * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map. + * This can be done explicitly, by creating a number of surfaces and + * attaching them with AddAttachedSurface or by implicitly by CreateSurface. + * If this bit is set then DDSCAPS_TEXTURE must also be set. + */ +#define DDSCAPS_MIPMAP 0x00400000l + + + +/* + * Indicates that memory for the surface is not allocated until the surface + * is loaded (via the Direct3D texture Load() function). + */ +#define DDSCAPS_ALLOCONLOAD 0x04000000l + + + + /**************************************************************************** + * + * DIRECTDRAW DRIVER CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Display hardware has 3D acceleration. + */ +#define DDCAPS_3D 0x00000001l + +/* + * Indicates that DirectDraw will support only dest rectangles that are aligned + * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively. + * READ ONLY. + */ +#define DDCAPS_ALIGNBOUNDARYDEST 0x00000002l + +/* + * Indicates that DirectDraw will support only source rectangles whose sizes in + * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively. READ ONLY. + */ +#define DDCAPS_ALIGNSIZEDEST 0x00000004l +/* + * Indicates that DirectDraw will support only source rectangles that are aligned + * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively. + * READ ONLY. + */ +#define DDCAPS_ALIGNBOUNDARYSRC 0x00000008l + +/* + * Indicates that DirectDraw will support only source rectangles whose sizes in + * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively. READ ONLY. + */ +#define DDCAPS_ALIGNSIZESRC 0x00000010l + +/* + * Indicates that DirectDraw will create video memory surfaces that have a stride + * alignment equal to DIRECTDRAWCAPS.dwAlignStride. READ ONLY. + */ +#define DDCAPS_ALIGNSTRIDE 0x00000020l + +/* + * Display hardware is capable of blt operations. + */ +#define DDCAPS_BLT 0x00000040l + +/* + * Display hardware is capable of asynchronous blt operations. + */ +#define DDCAPS_BLTQUEUE 0x00000080l + +/* + * Display hardware is capable of color space conversions during the blt operation. + */ +#define DDCAPS_BLTFOURCC 0x00000100l + +/* + * Display hardware is capable of stretching during blt operations. + */ +#define DDCAPS_BLTSTRETCH 0x00000200l + +/* + * Display hardware is shared with GDI. + */ +#define DDCAPS_GDI 0x00000400l + +/* + * Display hardware can overlay. + */ +#define DDCAPS_OVERLAY 0x00000800l + +/* + * Set if display hardware supports overlays but can not clip them. + */ +#define DDCAPS_OVERLAYCANTCLIP 0x00001000l + +/* + * Indicates that overlay hardware is capable of color space conversions during + * the overlay operation. + */ +#define DDCAPS_OVERLAYFOURCC 0x00002000l + +/* + * Indicates that stretching can be done by the overlay hardware. + */ +#define DDCAPS_OVERLAYSTRETCH 0x00004000l + +/* + * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces + * other than the primary surface. + */ +#define DDCAPS_PALETTE 0x00008000l + +/* + * Indicates that palette changes can be syncd with the veritcal refresh. + */ +#define DDCAPS_PALETTEVSYNC 0x00010000l + +/* + * Display hardware can return the current scan line. + */ +#define DDCAPS_READSCANLINE 0x00020000l + +/* + * Display hardware has stereo vision capabilities. DDSCAPS_PRIMARYSURFACELEFT + * can be created. + */ +#define DDCAPS_STEREOVIEW 0x00040000l + +/* + * Display hardware is capable of generating a vertical blank interrupt. + */ +#define DDCAPS_VBI 0x00080000l + +/* + * Supports the use of z buffers with blt operations. + */ +#define DDCAPS_ZBLTS 0x00100000l + +/* + * Supports Z Ordering of overlays. + */ +#define DDCAPS_ZOVERLAYS 0x00200000l + +/* + * Supports color key + */ +#define DDCAPS_COLORKEY 0x00400000l + +/* + * Supports alpha surfaces + */ +#define DDCAPS_ALPHA 0x00800000l + +/* + * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set) + */ +#define DDCAPS_COLORKEYHWASSIST 0x01000000l + +/* + * no hardware support at all + */ +#define DDCAPS_NOHARDWARE 0x02000000l + +/* + * Display hardware is capable of color fill with bltter + */ +#define DDCAPS_BLTCOLORFILL 0x04000000l + +/* + * Display hardware is bank switched, and potentially very slow at + * random access to VRAM. + */ +#define DDCAPS_BANKSWITCHED 0x08000000l + +/* + * Display hardware is capable of depth filling Z-buffers with bltter + */ +#define DDCAPS_BLTDEPTHFILL 0x10000000l + +/* + * Display hardware is capable of clipping while bltting. + */ +#define DDCAPS_CANCLIP 0x20000000l + +/* + * Display hardware is capable of clipping while stretch bltting. + */ +#define DDCAPS_CANCLIPSTRETCHED 0x40000000l + +/* + * Display hardware is capable of bltting to or from system memory + */ +#define DDCAPS_CANBLTSYSMEM 0x80000000l + + + /**************************************************************************** + * + * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2) + * + ****************************************************************************/ + +/* + * Display hardware is certified + */ +#define DDCAPS2_CERTIFIED 0x00000001l + +/* + * Driver cannot interleave 2D operations (lock and blt) to surfaces with + * Direct3D rendering operations between calls to BeginScene() and EndScene() + */ +#define DDCAPS2_NO2DDURING3DSCENE 0x00000002l + +/**************************************************************************** + * + * DIRECTDRAW FX ALPHA CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Supports alpha blending around the edge of a source color keyed surface. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAEDGEBLEND 0x00000001l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value becomes + * more opaque as the alpha value increases. (0 is transparent.) + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAPIXELS 0x00000002l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value + * becomes more transparent as the alpha value increases. (0 is opaque.) + * This flag can only be set if DDCAPS_ALPHA is set. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAPIXELSNEG 0x00000004l + +/* + * Supports alpha only surfaces. The bit depth of an alpha only surface can be + * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. + * (0 is transparent.) + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHASURFACES 0x00000008l + +/* + * The depth of the alpha channel data can range can be 1,2,4, or 8. + * The NEG suffix indicates that this alpha channel becomes more transparent + * as the alpha value increases. (0 is opaque.) This flag can only be set if + * DDCAPS_ALPHA is set. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHASURFACESNEG 0x00000010l + +/* + * Supports alpha blending around the edge of a source color keyed surface. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND 0x00000020l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value becomes + * more opaque as the alpha value increases. (0 is transparent.) + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAPIXELS 0x00000040l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value + * becomes more transparent as the alpha value increases. (0 is opaque.) + * This flag can only be set if DDCAPS_ALPHA is set. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG 0x00000080l + +/* + * Supports alpha only surfaces. The bit depth of an alpha only surface can be + * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. + * (0 is transparent.) + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHASURFACES 0x00000100l + +/* + * The depth of the alpha channel data can range can be 1,2,4, or 8. + * The NEG suffix indicates that this alpha channel becomes more transparent + * as the alpha value increases. (0 is opaque.) This flag can only be set if + * DDCAPS_ALPHA is set. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG 0x00000200l + +/**************************************************************************** + * + * DIRECTDRAW FX CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Uses arithmetic operations to stretch and shrink surfaces during blt + * rather than pixel doubling techniques. Along the Y axis. + */ +#define DDFXCAPS_BLTARITHSTRETCHY 0x00000020l + +/* + * Uses arithmetic operations to stretch during blt + * rather than pixel doubling techniques. Along the Y axis. Only + * works for x1, x2, etc. + */ +#define DDFXCAPS_BLTARITHSTRETCHYN 0x00000010l + +/* + * Supports mirroring left to right in blt. + */ +#define DDFXCAPS_BLTMIRRORLEFTRIGHT 0x00000040l + +/* + * Supports mirroring top to bottom in blt. + */ +#define DDFXCAPS_BLTMIRRORUPDOWN 0x00000080l + +/* + * Supports arbitrary rotation for blts. + */ +#define DDFXCAPS_BLTROTATION 0x00000100l + +/* + * Supports 90 degree rotations for blts. + */ +#define DDFXCAPS_BLTROTATION90 0x00000200l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKX 0x00000400l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKXN 0x00000800l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * y axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKY 0x00001000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the y axis (vertical direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKYN 0x00002000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHX 0x00004000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHXN 0x00008000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * y axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHY 0x00010000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the y axis (vertical direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHYN 0x00020000l + +/* + * Uses arithmetic operations to stretch and shrink surfaces during + * overlay rather than pixel doubling techniques. Along the Y axis + * for overlays. + */ +#define DDFXCAPS_OVERLAYARITHSTRETCHY 0x00040000l + +/* + * Uses arithmetic operations to stretch surfaces during + * overlay rather than pixel doubling techniques. Along the Y axis + * for overlays. Only works for x1, x2, etc. + */ +#define DDFXCAPS_OVERLAYARITHSTRETCHYN 0x00000008l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKX 0x00080000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKXN 0x00100000l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * y axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKY 0x00200000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the y axis (vertical direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKYN 0x00400000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHX 0x00800000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHXN 0x01000000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * y axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHY 0x02000000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the y axis (vertical direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHYN 0x04000000l + +/* + * DirectDraw supports mirroring of overlays across the vertical axis + */ +#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l + +/* + * DirectDraw supports mirroring of overlays across the horizontal axis + */ +#define DDFXCAPS_OVERLAYMIRRORUPDOWN 0x10000000l + +/**************************************************************************** + * + * DIRECTDRAW STEREO VIEW CAPABILITIES + * + ****************************************************************************/ + +/* + * The stereo view is accomplished via enigma encoding. + */ +#define DDSVCAPS_ENIGMA 0x00000001l + +/* + * The stereo view is accomplished via high frequency flickering. + */ +#define DDSVCAPS_FLICKER 0x00000002l + +/* + * The stereo view is accomplished via red and blue filters applied + * to the left and right eyes. All images must adapt their colorspaces + * for this process. + */ +#define DDSVCAPS_REDBLUE 0x00000004l + +/* + * The stereo view is accomplished with split screen technology. + */ +#define DDSVCAPS_SPLIT 0x00000008l + +/**************************************************************************** + * + * DIRECTDRAWPALETTE CAPABILITIES + * + ****************************************************************************/ + +/* + * Index is 4 bits. There are sixteen color entries in the palette table. + */ +#define DDPCAPS_4BIT 0x00000001l + +/* + * Index is onto a 8 bit color index. This field is only valid with the + * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target + * surface is in 8bpp. Each color entry is one byte long and is an index + * into destination surface's 8bpp palette. + */ +#define DDPCAPS_8BITENTRIES 0x00000002l + +/* + * Index is 8 bits. There are 256 color entries in the palette table. + */ +#define DDPCAPS_8BIT 0x00000004l + +/* + * Indicates that this DIRECTDRAWPALETTE should use the palette color array + * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE + * object. + */ +#define DDPCAPS_INITIALIZE 0x00000008l + +/* + * This palette is the one attached to the primary surface. Changing this + * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified + * and supported. + */ +#define DDPCAPS_PRIMARYSURFACE 0x00000010l + +/* + * This palette is the one attached to the primary surface left. Changing + * this table has immediate effect on the display for the left eye unless + * DDPSETPAL_VSYNC is specified and supported. + */ +#define DDPCAPS_PRIMARYSURFACELEFT 0x00000020l + +/* + * This palette can have all 256 entries defined + */ +#define DDPCAPS_ALLOW256 0x00000040l + +/* + * This palette can have modifications to it synced with the monitors + * refresh rate. + */ +#define DDPCAPS_VSYNC 0x00000080l + +/* + * Index is 1 bit. There are two color entries in the palette table. + */ +#define DDPCAPS_1BIT 0x00000100l + +/* + * Index is 2 bit. There are four color entries in the palette table. + */ +#define DDPCAPS_2BIT 0x00000200l + + +/**************************************************************************** + * + * DIRECTDRAWPALETTE SETENTRY CONSTANTS + * + ****************************************************************************/ + + +/**************************************************************************** + * + * DIRECTDRAWPALETTE GETENTRY CONSTANTS + * + ****************************************************************************/ + +/* 0 is the only legal value */ + +/**************************************************************************** + * + * DIRECTDRAWSURFACE SETPALETTE CONSTANTS + * + ****************************************************************************/ + + +/**************************************************************************** + * + * DIRECTDRAW BITDEPTH CONSTANTS + * + * NOTE: These are only used to indicate supported bit depths. These + * are flags only, they are not to be used as an actual bit depth. The + * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual + * bit depths in a surface or for changing the display mode. + * + ****************************************************************************/ + +/* + * 1 bit per pixel. + */ +#define DDBD_1 0x00004000l + +/* + * 2 bits per pixel. + */ +#define DDBD_2 0x00002000l + +/* + * 4 bits per pixel. + */ +#define DDBD_4 0x00001000l + +/* + * 8 bits per pixel. + */ +#define DDBD_8 0x00000800l + +/* + * 16 bits per pixel. + */ +#define DDBD_16 0x00000400l + +/* + * 24 bits per pixel. + */ +#define DDBD_24 0X00000200l + +/* + * 32 bits per pixel. + */ +#define DDBD_32 0x00000100l + +/**************************************************************************** + * + * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS + * + ****************************************************************************/ + +/* + * Set if the structure contains a color space. Not set if the structure + * contains a single color key. + */ +#define DDCKEY_COLORSPACE 0x00000001l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a destination color key for blt operations. + */ +#define DDCKEY_DESTBLT 0x00000002l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a destination color key for overlay operations. + */ +#define DDCKEY_DESTOVERLAY 0x00000004l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a source color key for blt operations. + */ +#define DDCKEY_SRCBLT 0x00000008l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a source color key for overlay operations. + */ +#define DDCKEY_SRCOVERLAY 0x00000010l + + +/**************************************************************************** + * + * DIRECTDRAW COLOR KEY CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Supports transparent blting using a color key to identify the replaceable + * bits of the destination surface for RGB colors. + */ +#define DDCKEYCAPS_DESTBLT 0x00000001l + +/* + * Supports transparent blting using a color space to identify the replaceable + * bits of the destination surface for RGB colors. + */ +#define DDCKEYCAPS_DESTBLTCLRSPACE 0x00000002l + +/* + * Supports transparent blting using a color space to identify the replaceable + * bits of the destination surface for YUV colors. + */ +#define DDCKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004l + +/* + * Supports transparent blting using a color key to identify the replaceable + * bits of the destination surface for YUV colors. + */ +#define DDCKEYCAPS_DESTBLTYUV 0x00000008l + +/* + * Supports overlaying using colorkeying of the replaceable bits of the surface + * being overlayed for RGB colors. + */ +#define DDCKEYCAPS_DESTOVERLAY 0x00000010l + +/* + * Supports a color space as the color key for the destination for RGB colors. + */ +#define DDCKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020l + +/* + * Supports a color space as the color key for the destination for YUV colors. + */ +#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040l + +/* + * Supports only one active destination color key value for visible overlay + * surfaces. + */ +#define DDCKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080l + +/* + * Supports overlaying using colorkeying of the replaceable bits of the + * surface being overlayed for YUV colors. + */ +#define DDCKEYCAPS_DESTOVERLAYYUV 0x00000100l + +/* + * Supports transparent blting using the color key for the source with + * this surface for RGB colors. + */ +#define DDCKEYCAPS_SRCBLT 0x00000200l + +/* + * Supports transparent blting using a color space for the source with + * this surface for RGB colors. + */ +#define DDCKEYCAPS_SRCBLTCLRSPACE 0x00000400l + +/* + * Supports transparent blting using a color space for the source with + * this surface for YUV colors. + */ +#define DDCKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800l + +/* + * Supports transparent blting using the color key for the source with + * this surface for YUV colors. + */ +#define DDCKEYCAPS_SRCBLTYUV 0x00001000l + +/* + * Supports overlays using the color key for the source with this + * overlay surface for RGB colors. + */ +#define DDCKEYCAPS_SRCOVERLAY 0x00002000l + +/* + * Supports overlays using a color space as the source color key for + * the overlay surface for RGB colors. + */ +#define DDCKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000l + +/* + * Supports overlays using a color space as the source color key for + * the overlay surface for YUV colors. + */ +#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000l + +/* + * Supports only one active source color key value for visible + * overlay surfaces. + */ +#define DDCKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000l + +/* + * Supports overlays using the color key for the source with this + * overlay surface for YUV colors. + */ +#define DDCKEYCAPS_SRCOVERLAYYUV 0x00020000l + +/* + * there are no bandwidth trade-offs for using colorkey with an overlay + */ +#define DDCKEYCAPS_NOCOSTOVERLAY 0x00040000l + + +/**************************************************************************** + * + * DIRECTDRAW PIXELFORMAT FLAGS + * + ****************************************************************************/ + +/* + * The surface has alpha channel information in the pixel format. + */ +#define DDPF_ALPHAPIXELS 0x00000001l + +/* + * The pixel format contains alpha only information + */ +#define DDPF_ALPHA 0x00000002l + +/* + * The FourCC code is valid. + */ +#define DDPF_FOURCC 0x00000004l + +/* + * The surface is 4-bit color indexed. + */ +#define DDPF_PALETTEINDEXED4 0x00000008l + +/* + * The surface is indexed into a palette which stores indices + * into the destination surface's 8-bit palette. + */ +#define DDPF_PALETTEINDEXEDTO8 0x00000010l + +/* + * The surface is 8-bit color indexed. + */ +#define DDPF_PALETTEINDEXED8 0x00000020l + +/* + * The RGB data in the pixel format structure is valid. + */ +#define DDPF_RGB 0x00000040l + +/* + * The surface will accept pixel data in the format specified + * and compress it during the write. + */ +#define DDPF_COMPRESSED 0x00000080l + +/* + * The surface will accept RGB data and translate it during + * the write to YUV data. The format of the data to be written + * will be contained in the pixel format structure. The DDPF_RGB + * flag will be set. + */ +#define DDPF_RGBTOYUV 0x00000100l + +/* + * pixel format is YUV - YUV data in pixel format struct is valid + */ +#define DDPF_YUV 0x00000200l + +/* + * pixel format is a z buffer only surface + */ +#define DDPF_ZBUFFER 0x00000400l + +/* + * The surface is 1-bit color indexed. + */ +#define DDPF_PALETTEINDEXED1 0x00000800l + +/* + * The surface is 2-bit color indexed. + */ +#define DDPF_PALETTEINDEXED2 0x00001000l + +/*=========================================================================== + * + * + * DIRECTDRAW CALLBACK FLAGS + * + * + *==========================================================================*/ + +/**************************************************************************** + * + * DIRECTDRAW ENUMSURFACES FLAGS + * + ****************************************************************************/ + +/* + * Enumerate all of the surfaces that meet the search criterion. + */ +#define DDENUMSURFACES_ALL 0x00000001l + +/* + * A search hit is a surface that matches the surface description. + */ +#define DDENUMSURFACES_MATCH 0x00000002l + +/* + * A search hit is a surface that does not match the surface description. + */ +#define DDENUMSURFACES_NOMATCH 0x00000004l + +/* + * Enumerate the first surface that can be created which meets the search criterion. + */ +#define DDENUMSURFACES_CANBECREATED 0x00000008l + +/* + * Enumerate the surfaces that already exist that meet the search criterion. + */ +#define DDENUMSURFACES_DOESEXIST 0x00000010l + + +/**************************************************************************** + * + * DIRECTDRAW ENUMDISPLAYMODES FLAGS + * + ****************************************************************************/ + +/* + * Enumerate Modes with different refresh rates. EnumDisplayModes guarantees + * that a particular mode will be enumerated only once. This flag specifies whether + * the refresh rate is taken into account when determining if a mode is unique. + */ +#define DDEDM_REFRESHRATES 0x00000001l + + +/**************************************************************************** + * + * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS + * + ****************************************************************************/ + +/* + * Exclusive mode owner will be responsible for the entire primary surface. + * GDI can be ignored. used with DD + */ +#define DDSCL_FULLSCREEN 0x00000001l + +/* + * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode + */ +#define DDSCL_ALLOWREBOOT 0x00000002l + +/* + * prevents DDRAW from modifying the application window. + * prevents DDRAW from minimize/restore the application window on activation. + */ +#define DDSCL_NOWINDOWCHANGES 0x00000004l + +/* + * app wants to work as a regular Windows application + */ +#define DDSCL_NORMAL 0x00000008l + +/* + * app wants exclusive access + */ +#define DDSCL_EXCLUSIVE 0x00000010l + + +/* + * app can deal with non-windows display modes + */ +#define DDSCL_ALLOWMODEX 0x00000040l + + +/**************************************************************************** + * + * DIRECTDRAW BLT FLAGS + * + ****************************************************************************/ + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the destination surface as the alpha channel for this blt. + */ +#define DDBLT_ALPHADEST 0x00000001l + +/* + * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel + * for the destination surface for this blt. + */ +#define DDBLT_ALPHADESTCONSTOVERRIDE 0x00000002l + +/* + * The NEG suffix indicates that the destination surface becomes more + * transparent as the alpha value increases. (0 is opaque) + */ +#define DDBLT_ALPHADESTNEG 0x00000004l + +/* + * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha + * channel for the destination for this blt. + */ +#define DDBLT_ALPHADESTSURFACEOVERRIDE 0x00000008l + +/* + * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel + * for the edges of the image that border the color key colors. + */ +#define DDBLT_ALPHAEDGEBLEND 0x00000010l + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the source surface as the alpha channel for this blt. + */ +#define DDBLT_ALPHASRC 0x00000020l + +/* + * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel + * for the source for this blt. + */ +#define DDBLT_ALPHASRCCONSTOVERRIDE 0x00000040l + +/* + * The NEG suffix indicates that the source surface becomes more transparent + * as the alpha value increases. (0 is opaque) + */ +#define DDBLT_ALPHASRCNEG 0x00000080l + +/* + * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel + * for the source for this blt. + */ +#define DDBLT_ALPHASRCSURFACEOVERRIDE 0x00000100l + +/* + * Do this blt asynchronously through the FIFO in the order received. If + * there is no room in the hardware FIFO fail the call. + */ +#define DDBLT_ASYNC 0x00000200l + +/* + * Uses the dwFillColor field in the DDBLTFX structure as the RGB color + * to fill the destination rectangle on the destination surface with. + */ +#define DDBLT_COLORFILL 0x00000400l + +/* + * Uses the dwDDFX field in the DDBLTFX structure to specify the effects + * to use for the blt. + */ +#define DDBLT_DDFX 0x00000800l + +/* + * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS + * that are not part of the Win32 API. + */ +#define DDBLT_DDROPS 0x00001000l + +/* + * Use the color key associated with the destination surface. + */ +#define DDBLT_KEYDEST 0x00002000l + +/* + * Use the dckDestColorkey field in the DDBLTFX structure as the color key + * for the destination surface. + */ +#define DDBLT_KEYDESTOVERRIDE 0x00004000l + +/* + * Use the color key associated with the source surface. + */ +#define DDBLT_KEYSRC 0x00008000l + +/* + * Use the dckSrcColorkey field in the DDBLTFX structure as the color key + * for the source surface. + */ +#define DDBLT_KEYSRCOVERRIDE 0x00010000l + +/* + * Use the dwROP field in the DDBLTFX structure for the raster operation + * for this blt. These ROPs are the same as the ones defined in the Win32 API. + */ +#define DDBLT_ROP 0x00020000l + +/* + * Use the dwRotationAngle field in the DDBLTFX structure as the angle + * (specified in 1/100th of a degree) to rotate the surface. + */ +#define DDBLT_ROTATIONANGLE 0x00040000l + +/* + * Z-buffered blt using the z-buffers attached to the source and destination + * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the + * z-buffer opcode. + */ +#define DDBLT_ZBUFFER 0x00080000l + +/* + * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field + * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively + * for the destination. + */ +#define DDBLT_ZBUFFERDESTCONSTOVERRIDE 0x00100000l + +/* + * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode + * field in the DDBLTFX structure as the z-buffer and z-buffer opcode + * respectively for the destination. + */ +#define DDBLT_ZBUFFERDESTOVERRIDE 0x00200000l + +/* + * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field + * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively + * for the source. + */ +#define DDBLT_ZBUFFERSRCCONSTOVERRIDE 0x00400000l + +/* + * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode + * field in the DDBLTFX structure as the z-buffer and z-buffer opcode + * respectively for the source. + */ +#define DDBLT_ZBUFFERSRCOVERRIDE 0x00800000l + +/* + * wait until the device is ready to handle the blt + * this will cause blt to not return DDERR_WASSTILLDRAWING + */ +#define DDBLT_WAIT 0x01000000l + +/* + * Uses the dwFillDepth field in the DDBLTFX structure as the depth value + * to fill the destination rectangle on the destination Z-buffer surface + * with. + */ +#define DDBLT_DEPTHFILL 0x02000000l + + +/**************************************************************************** + * + * BLTFAST FLAGS + * + ****************************************************************************/ + +#define DDBLTFAST_NOCOLORKEY 0x00000000 +#define DDBLTFAST_SRCCOLORKEY 0x00000001 +#define DDBLTFAST_DESTCOLORKEY 0x00000002 +#define DDBLTFAST_WAIT 0x00000010 + +/**************************************************************************** + * + * FLIP FLAGS + * + ****************************************************************************/ + +#define DDFLIP_WAIT 0x00000001l + + +/**************************************************************************** + * + * DIRECTDRAW SURFACE OVERLAY FLAGS + * + ****************************************************************************/ + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the destination surface as the alpha channel for the + * destination overlay. + */ +#define DDOVER_ALPHADEST 0x00000001l + +/* + * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the + * destination alpha channel for this overlay. + */ +#define DDOVER_ALPHADESTCONSTOVERRIDE 0x00000002l + +/* + * The NEG suffix indicates that the destination surface becomes more + * transparent as the alpha value increases. + */ +#define DDOVER_ALPHADESTNEG 0x00000004l + +/* + * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha + * channel destination for this overlay. + */ +#define DDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008l + +/* + * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha + * channel for the edges of the image that border the color key colors. + */ +#define DDOVER_ALPHAEDGEBLEND 0x00000010l + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the source surface as the source alpha channel for this overlay. + */ +#define DDOVER_ALPHASRC 0x00000020l + +/* + * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source + * alpha channel for this overlay. + */ +#define DDOVER_ALPHASRCCONSTOVERRIDE 0x00000040l + +/* + * The NEG suffix indicates that the source surface becomes more transparent + * as the alpha value increases. + */ +#define DDOVER_ALPHASRCNEG 0x00000080l + +/* + * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel + * source for this overlay. + */ +#define DDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100l + +/* + * Turn this overlay off. + */ +#define DDOVER_HIDE 0x00000200l + +/* + * Use the color key associated with the destination surface. + */ +#define DDOVER_KEYDEST 0x00000400l + +/* + * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key + * for the destination surface + */ +#define DDOVER_KEYDESTOVERRIDE 0x00000800l + +/* + * Use the color key associated with the source surface. + */ +#define DDOVER_KEYSRC 0x00001000l + +/* + * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key + * for the source surface. + */ +#define DDOVER_KEYSRCOVERRIDE 0x00002000l + +/* + * Turn this overlay on. + */ +#define DDOVER_SHOW 0x00004000l + +/* + * Add a dirty rect to an emulated overlayed surface. + */ +#define DDOVER_ADDDIRTYRECT 0x00008000l + +/* + * Redraw all dirty rects on an emulated overlayed surface. + */ +#define DDOVER_REFRESHDIRTYRECTS 0x00010000l + +/* + * Redraw the entire surface on an emulated overlayed surface. + */ +#define DDOVER_REFRESHALL 0x00020000l + + +/* + * Use the overlay FX flags to define special overlay FX + */ +#define DDOVER_DDFX 0x00080000l + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE LOCK FLAGS + * + ****************************************************************************/ + +/* + * The default. Set to indicate that Lock should return a valid memory pointer + * to the top of the specified rectangle. If no rectangle is specified then a + * pointer to the top of the surface is returned. + */ +#define DDLOCK_SURFACEMEMORYPTR 0x00000000L // default + +/* + * Set to indicate that Lock should wait until it can obtain a valid memory + * pointer before returning. If this bit is set, Lock will never return + * DDERR_WASSTILLDRAWING. + */ +#define DDLOCK_WAIT 0x00000001L + +/* + * Set if an event handle is being passed to Lock. Lock will trigger the event + * when it can return the surface memory pointer requested. + */ +#define DDLOCK_EVENT 0x00000002L + +/* + * Indicates that the surface being locked will only be read from. + */ +#define DDLOCK_READONLY 0x00000010L + +/* + * Indicates that the surface being locked will only be written to + */ +#define DDLOCK_WRITEONLY 0x00000020L + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE PAGELOCK FLAGS + * + ****************************************************************************/ + +/* + * No flags defined at present + */ + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS + * + ****************************************************************************/ + +/* + * No flags defined at present + */ + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE BLT FX FLAGS + * + ****************************************************************************/ + +/* + * If stretching, use arithmetic stretching along the Y axis for this blt. + */ +#define DDBLTFX_ARITHSTRETCHY 0x00000001l + +/* + * Do this blt mirroring the surface left to right. Spin the + * surface around its y-axis. + */ +#define DDBLTFX_MIRRORLEFTRIGHT 0x00000002l + +/* + * Do this blt mirroring the surface up and down. Spin the surface + * around its x-axis. + */ +#define DDBLTFX_MIRRORUPDOWN 0x00000004l + +/* + * Schedule this blt to avoid tearing. + */ +#define DDBLTFX_NOTEARING 0x00000008l + +/* + * Do this blt rotating the surface one hundred and eighty degrees. + */ +#define DDBLTFX_ROTATE180 0x00000010l + +/* + * Do this blt rotating the surface two hundred and seventy degrees. + */ +#define DDBLTFX_ROTATE270 0x00000020l + +/* + * Do this blt rotating the surface ninety degrees. + */ +#define DDBLTFX_ROTATE90 0x00000040l + +/* + * Do this z blt using dwZBufferLow and dwZBufferHigh as range values + * specified to limit the bits copied from the source surface. + */ +#define DDBLTFX_ZBUFFERRANGE 0x00000080l + +/* + * Do this z blt adding the dwZBufferBaseDest to each of the sources z values + * before comparing it with the desting z values. + */ +#define DDBLTFX_ZBUFFERBASEDEST 0x00000100l + +/**************************************************************************** + * + * DIRECTDRAWSURFACE OVERLAY FX FLAGS + * + ****************************************************************************/ + +/* + * If stretching, use arithmetic stretching along the Y axis for this overlay. + */ +#define DDOVERFX_ARITHSTRETCHY 0x00000001l + +/* + * Mirror the overlay across the vertical axis + */ +#define DDOVERFX_MIRRORLEFTRIGHT 0x00000002l + +/* + * Mirror the overlay across the horizontal axis + */ +#define DDOVERFX_MIRRORUPDOWN 0x00000004l + +/**************************************************************************** + * + * DIRECTDRAW WAITFORVERTICALBLANK FLAGS + * + ****************************************************************************/ + +/* + * return when the vertical blank interval begins + */ +#define DDWAITVB_BLOCKBEGIN 0x00000001l + +/* + * set up an event to trigger when the vertical blank begins + */ +#define DDWAITVB_BLOCKBEGINEVENT 0x00000002l + +/* + * return when the vertical blank interval ends and display begins + */ +#define DDWAITVB_BLOCKEND 0x00000004l + +/**************************************************************************** + * + * DIRECTDRAW GETFLIPSTATUS FLAGS + * + ****************************************************************************/ + +/* + * is it OK to flip now? + */ +#define DDGFS_CANFLIP 0x00000001l + +/* + * is the last flip finished? + */ +#define DDGFS_ISFLIPDONE 0x00000002l + +/**************************************************************************** + * + * DIRECTDRAW GETBLTSTATUS FLAGS + * + ****************************************************************************/ + +/* + * is it OK to blt now? + */ +#define DDGBS_CANBLT 0x00000001l + +/* + * is the blt to the surface finished? + */ +#define DDGBS_ISBLTDONE 0x00000002l + + +/**************************************************************************** + * + * DIRECTDRAW ENUMOVERLAYZORDER FLAGS + * + ****************************************************************************/ + +/* + * Enumerate overlays back to front. + */ +#define DDENUMOVERLAYZ_BACKTOFRONT 0x00000000l + +/* + * Enumerate overlays front to back + */ +#define DDENUMOVERLAYZ_FRONTTOBACK 0x00000001l + +/**************************************************************************** + * + * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS + * + ****************************************************************************/ + +/* + * Send overlay to front + */ +#define DDOVERZ_SENDTOFRONT 0x00000000l + +/* + * Send overlay to back + */ +#define DDOVERZ_SENDTOBACK 0x00000001l + +/* + * Move Overlay forward + */ +#define DDOVERZ_MOVEFORWARD 0x00000002l + +/* + * Move Overlay backward + */ +#define DDOVERZ_MOVEBACKWARD 0x00000003l + +/* + * Move Overlay in front of relative surface + */ +#define DDOVERZ_INSERTINFRONTOF 0x00000004l + +/* + * Move Overlay in back of relative surface + */ +#define DDOVERZ_INSERTINBACKOF 0x00000005l + +/*=========================================================================== + * + * + * DIRECTDRAW RETURN CODES + * + * The return values from DirectDraw Commands and Surface that return an HRESULT + * are codes from DirectDraw concerning the results of the action + * requested by DirectDraw. + * + *==========================================================================*/ + +/* + * Status is OK + * + * Issued by: DirectDraw Commands and all callbacks + */ +#define DD_OK 0 + +/**************************************************************************** + * + * DIRECTDRAW ENUMCALLBACK RETURN VALUES + * + * EnumCallback returns are used to control the flow of the DIRECTDRAW and + * DIRECTDRAWSURFACE object enumerations. They can only be returned by + * enumeration callback routines. + * + ****************************************************************************/ + +/* + * stop the enumeration + */ +#define DDENUMRET_CANCEL 0 + +/* + * continue the enumeration + */ +#define DDENUMRET_OK 1 + +/**************************************************************************** + * + * DIRECTDRAW ERRORS + * + * Errors are represented by negative values and cannot be combined. + * + ****************************************************************************/ + +/* + * This object is already initialized + */ +#define DDERR_ALREADYINITIALIZED MAKE_DDHRESULT( 5 ) + +/* + * This surface can not be attached to the requested surface. + */ +#define DDERR_CANNOTATTACHSURFACE MAKE_DDHRESULT( 10 ) + +/* + * This surface can not be detached from the requested surface. + */ +#define DDERR_CANNOTDETACHSURFACE MAKE_DDHRESULT( 20 ) + +/* + * Support is currently not available. + */ +#define DDERR_CURRENTLYNOTAVAIL MAKE_DDHRESULT( 40 ) + +/* + * An exception was encountered while performing the requested operation + */ +#define DDERR_EXCEPTION MAKE_DDHRESULT( 55 ) + +/* + * Generic failure. + */ +#define DDERR_GENERIC E_FAIL + +/* + * Height of rectangle provided is not a multiple of reqd alignment + */ +#define DDERR_HEIGHTALIGN MAKE_DDHRESULT( 90 ) + +/* + * Unable to match primary surface creation request with existing + * primary surface. + */ +#define DDERR_INCOMPATIBLEPRIMARY MAKE_DDHRESULT( 95 ) + +/* + * One or more of the caps bits passed to the callback are incorrect. + */ +#define DDERR_INVALIDCAPS MAKE_DDHRESULT( 100 ) + +/* + * DirectDraw does not support provided Cliplist. + */ +#define DDERR_INVALIDCLIPLIST MAKE_DDHRESULT( 110 ) + +/* + * DirectDraw does not support the requested mode + */ +#define DDERR_INVALIDMODE MAKE_DDHRESULT( 120 ) + +/* + * DirectDraw received a pointer that was an invalid DIRECTDRAW object. + */ +#define DDERR_INVALIDOBJECT MAKE_DDHRESULT( 130 ) + +/* + * One or more of the parameters passed to the callback function are + * incorrect. + */ +#define DDERR_INVALIDPARAMS E_INVALIDARG + +/* + * pixel format was invalid as specified + */ +#define DDERR_INVALIDPIXELFORMAT MAKE_DDHRESULT( 145 ) + +/* + * Rectangle provided was invalid. + */ +#define DDERR_INVALIDRECT MAKE_DDHRESULT( 150 ) + +/* + * Operation could not be carried out because one or more surfaces are locked + */ +#define DDERR_LOCKEDSURFACES MAKE_DDHRESULT( 160 ) + +/* + * There is no 3D present. + */ +#define DDERR_NO3D MAKE_DDHRESULT( 170 ) + +/* + * Operation could not be carried out because there is no alpha accleration + * hardware present or available. + */ +#define DDERR_NOALPHAHW MAKE_DDHRESULT( 180 ) + + +/* + * no clip list available + */ +#define DDERR_NOCLIPLIST MAKE_DDHRESULT( 205 ) + +/* + * Operation could not be carried out because there is no color conversion + * hardware present or available. + */ +#define DDERR_NOCOLORCONVHW MAKE_DDHRESULT( 210 ) + +/* + * Create function called without DirectDraw object method SetCooperativeLevel + * being called. + */ +#define DDERR_NOCOOPERATIVELEVELSET MAKE_DDHRESULT( 212 ) + +/* + * Surface doesn't currently have a color key + */ +#define DDERR_NOCOLORKEY MAKE_DDHRESULT( 215 ) + +/* + * Operation could not be carried out because there is no hardware support + * of the dest color key. + */ +#define DDERR_NOCOLORKEYHW MAKE_DDHRESULT( 220 ) + +/* + * No DirectDraw support possible with current display driver + */ +#define DDERR_NODIRECTDRAWSUPPORT MAKE_DDHRESULT( 222 ) + +/* + * Operation requires the application to have exclusive mode but the + * application does not have exclusive mode. + */ +#define DDERR_NOEXCLUSIVEMODE MAKE_DDHRESULT( 225 ) + +/* + * Flipping visible surfaces is not supported. + */ +#define DDERR_NOFLIPHW MAKE_DDHRESULT( 230 ) + +/* + * There is no GDI present. + */ +#define DDERR_NOGDI MAKE_DDHRESULT( 240 ) + +/* + * Operation could not be carried out because there is no hardware present + * or available. + */ +#define DDERR_NOMIRRORHW MAKE_DDHRESULT( 250 ) + +/* + * Requested item was not found + */ +#define DDERR_NOTFOUND MAKE_DDHRESULT( 255 ) + +/* + * Operation could not be carried out because there is no overlay hardware + * present or available. + */ +#define DDERR_NOOVERLAYHW MAKE_DDHRESULT( 260 ) + +/* + * Operation could not be carried out because there is no appropriate raster + * op hardware present or available. + */ +#define DDERR_NORASTEROPHW MAKE_DDHRESULT( 280 ) + +/* + * Operation could not be carried out because there is no rotation hardware + * present or available. + */ +#define DDERR_NOROTATIONHW MAKE_DDHRESULT( 290 ) + +/* + * Operation could not be carried out because there is no hardware support + * for stretching + */ +#define DDERR_NOSTRETCHHW MAKE_DDHRESULT( 310 ) + +/* + * DirectDrawSurface is not in 4 bit color palette and the requested operation + * requires 4 bit color palette. + */ +#define DDERR_NOT4BITCOLOR MAKE_DDHRESULT( 316 ) + +/* + * DirectDrawSurface is not in 4 bit color index palette and the requested + * operation requires 4 bit color index palette. + */ +#define DDERR_NOT4BITCOLORINDEX MAKE_DDHRESULT( 317 ) + +/* + * DirectDraw Surface is not in 8 bit color mode and the requested operation + * requires 8 bit color. + */ +#define DDERR_NOT8BITCOLOR MAKE_DDHRESULT( 320 ) + +/* + * Operation could not be carried out because there is no texture mapping + * hardware present or available. + */ +#define DDERR_NOTEXTUREHW MAKE_DDHRESULT( 330 ) + +/* + * Operation could not be carried out because there is no hardware support + * for vertical blank synchronized operations. + */ +#define DDERR_NOVSYNCHW MAKE_DDHRESULT( 335 ) + +/* + * Operation could not be carried out because there is no hardware support + * for zbuffer blting. + */ +#define DDERR_NOZBUFFERHW MAKE_DDHRESULT( 340 ) + +/* + * Overlay surfaces could not be z layered based on their BltOrder because + * the hardware does not support z layering of overlays. + */ +#define DDERR_NOZOVERLAYHW MAKE_DDHRESULT( 350 ) + +/* + * The hardware needed for the requested operation has already been + * allocated. + */ +#define DDERR_OUTOFCAPS MAKE_DDHRESULT( 360 ) + +/* + * DirectDraw does not have enough memory to perform the operation. + */ +#define DDERR_OUTOFMEMORY E_OUTOFMEMORY + +/* + * DirectDraw does not have enough memory to perform the operation. + */ +#define DDERR_OUTOFVIDEOMEMORY MAKE_DDHRESULT( 380 ) + +/* + * hardware does not support clipped overlays + */ +#define DDERR_OVERLAYCANTCLIP MAKE_DDHRESULT( 382 ) + +/* + * Can only have ony color key active at one time for overlays + */ +#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE MAKE_DDHRESULT( 384 ) + +/* + * Access to this palette is being refused because the palette is already + * locked by another thread. + */ +#define DDERR_PALETTEBUSY MAKE_DDHRESULT( 387 ) + +/* + * No src color key specified for this operation. + */ +#define DDERR_COLORKEYNOTSET MAKE_DDHRESULT( 400 ) + +/* + * This surface is already attached to the surface it is being attached to. + */ +#define DDERR_SURFACEALREADYATTACHED MAKE_DDHRESULT( 410 ) + +/* + * This surface is already a dependency of the surface it is being made a + * dependency of. + */ +#define DDERR_SURFACEALREADYDEPENDENT MAKE_DDHRESULT( 420 ) + +/* + * Access to this surface is being refused because the surface is already + * locked by another thread. + */ +#define DDERR_SURFACEBUSY MAKE_DDHRESULT( 430 ) + +/* + * Access to this surface is being refused because no driver exists + * which can supply a pointer to the surface. + * This is most likely to happen when attempting to lock the primary + * surface when no DCI provider is present. + */ +#define DDERR_CANTLOCKSURFACE MAKE_DDHRESULT( 435 ) + +/* + * Access to Surface refused because Surface is obscured. + */ +#define DDERR_SURFACEISOBSCURED MAKE_DDHRESULT( 440 ) + +/* + * Access to this surface is being refused because the surface is gone. + * The DIRECTDRAWSURFACE object representing this surface should + * have Restore called on it. + */ +#define DDERR_SURFACELOST MAKE_DDHRESULT( 450 ) + +/* + * The requested surface is not attached. + */ +#define DDERR_SURFACENOTATTACHED MAKE_DDHRESULT( 460 ) + +/* + * Height requested by DirectDraw is too large. + */ +#define DDERR_TOOBIGHEIGHT MAKE_DDHRESULT( 470 ) + +/* + * Size requested by DirectDraw is too large -- The individual height and + * width are OK. + */ +#define DDERR_TOOBIGSIZE MAKE_DDHRESULT( 480 ) + +/* + * Width requested by DirectDraw is too large. + */ +#define DDERR_TOOBIGWIDTH MAKE_DDHRESULT( 490 ) + +/* + * Action not supported. + */ +#define DDERR_UNSUPPORTED E_NOTIMPL + +/* + * FOURCC format requested is unsupported by DirectDraw + */ +#define DDERR_UNSUPPORTEDFORMAT MAKE_DDHRESULT( 510 ) + +/* + * Bitmask in the pixel format requested is unsupported by DirectDraw + */ +#define DDERR_UNSUPPORTEDMASK MAKE_DDHRESULT( 520 ) + +/* + * vertical blank is in progress + */ +#define DDERR_VERTICALBLANKINPROGRESS MAKE_DDHRESULT( 537 ) + +/* + * Informs DirectDraw that the previous Blt which is transfering information + * to or from this Surface is incomplete. + */ +#define DDERR_WASSTILLDRAWING MAKE_DDHRESULT( 540 ) + +/* + * Rectangle provided was not horizontally aligned on reqd. boundary + */ +#define DDERR_XALIGN MAKE_DDHRESULT( 560 ) + +/* + * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver + * identifier. + */ +#define DDERR_INVALIDDIRECTDRAWGUID MAKE_DDHRESULT( 561 ) + +/* + * A DirectDraw object representing this driver has already been created + * for this process. + */ +#define DDERR_DIRECTDRAWALREADYCREATED MAKE_DDHRESULT( 562 ) + +/* + * A hardware only DirectDraw object creation was attempted but the driver + * did not support any hardware. + */ +#define DDERR_NODIRECTDRAWHW MAKE_DDHRESULT( 563 ) + +/* + * this process already has created a primary surface + */ +#define DDERR_PRIMARYSURFACEALREADYEXISTS MAKE_DDHRESULT( 564 ) + +/* + * software emulation not available. + */ +#define DDERR_NOEMULATION MAKE_DDHRESULT( 565 ) + +/* + * region passed to Clipper::GetClipList is too small. + */ +#define DDERR_REGIONTOOSMALL MAKE_DDHRESULT( 566 ) + +/* + * an attempt was made to set a clip list for a clipper objec that + * is already monitoring an hwnd. + */ +#define DDERR_CLIPPERISUSINGHWND MAKE_DDHRESULT( 567 ) + +/* + * No clipper object attached to surface object + */ +#define DDERR_NOCLIPPERATTACHED MAKE_DDHRESULT( 568 ) + +/* + * Clipper notification requires an HWND or + * no HWND has previously been set as the CooperativeLevel HWND. + */ +#define DDERR_NOHWND MAKE_DDHRESULT( 569 ) + +/* + * HWND used by DirectDraw CooperativeLevel has been subclassed, + * this prevents DirectDraw from restoring state. + */ +#define DDERR_HWNDSUBCLASSED MAKE_DDHRESULT( 570 ) + +/* + * The CooperativeLevel HWND has already been set. + * It can not be reset while the process has surfaces or palettes created. + */ +#define DDERR_HWNDALREADYSET MAKE_DDHRESULT( 571 ) + +/* + * No palette object attached to this surface. + */ +#define DDERR_NOPALETTEATTACHED MAKE_DDHRESULT( 572 ) + +/* + * No hardware support for 16 or 256 color palettes. + */ +#define DDERR_NOPALETTEHW MAKE_DDHRESULT( 573 ) + +/* + * If a clipper object is attached to the source surface passed into a + * BltFast call. + */ +#define DDERR_BLTFASTCANTCLIP MAKE_DDHRESULT( 574 ) + +/* + * No blter. + */ +#define DDERR_NOBLTHW MAKE_DDHRESULT( 575 ) + +/* + * No DirectDraw ROP hardware. + */ +#define DDERR_NODDROPSHW MAKE_DDHRESULT( 576 ) + +/* + * returned when GetOverlayPosition is called on a hidden overlay + */ +#define DDERR_OVERLAYNOTVISIBLE MAKE_DDHRESULT( 577 ) + +/* + * returned when GetOverlayPosition is called on a overlay that UpdateOverlay + * has never been called on to establish a destionation. + */ +#define DDERR_NOOVERLAYDEST MAKE_DDHRESULT( 578 ) + +/* + * returned when the position of the overlay on the destionation is no longer + * legal for that destionation. + */ +#define DDERR_INVALIDPOSITION MAKE_DDHRESULT( 579 ) + +/* + * returned when an overlay member is called for a non-overlay surface + */ +#define DDERR_NOTAOVERLAYSURFACE MAKE_DDHRESULT( 580 ) + +/* + * An attempt was made to set the cooperative level when it was already + * set to exclusive. + */ +#define DDERR_EXCLUSIVEMODEALREADYSET MAKE_DDHRESULT( 581 ) + +/* + * An attempt has been made to flip a surface that is not flippable. + */ +#define DDERR_NOTFLIPPABLE MAKE_DDHRESULT( 582 ) + +/* + * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly + * created. + */ +#define DDERR_CANTDUPLICATE MAKE_DDHRESULT( 583 ) + +/* + * Surface was not locked. An attempt to unlock a surface that was not + * locked at all, or by this process, has been attempted. + */ +#define DDERR_NOTLOCKED MAKE_DDHRESULT( 584 ) + +/* + * Windows can not create any more DCs + */ +#define DDERR_CANTCREATEDC MAKE_DDHRESULT( 585 ) + +/* + * No DC was ever created for this surface. + */ +#define DDERR_NODC MAKE_DDHRESULT( 586 ) + +/* + * This surface can not be restored because it was created in a different + * mode. + */ +#define DDERR_WRONGMODE MAKE_DDHRESULT( 587 ) + +/* + * This surface can not be restored because it is an implicitly created + * surface. + */ +#define DDERR_IMPLICITLYCREATED MAKE_DDHRESULT( 588 ) + +/* + * The surface being used is not a palette-based surface + */ +#define DDERR_NOTPALETTIZED MAKE_DDHRESULT( 589 ) + + +/* + * The display is currently in an unsupported mode + */ +#define DDERR_UNSUPPORTEDMODE MAKE_DDHRESULT( 590 ) + +/* + * Operation could not be carried out because there is no mip-map + * texture mapping hardware present or available. + */ +#define DDERR_NOMIPMAPHW MAKE_DDHRESULT( 591 ) + +/* + * The requested action could not be performed because the surface was of + * the wrong type. + */ +#define DDERR_INVALIDSURFACETYPE MAKE_DDHRESULT( 592 ) + + + +/* + * A DC has already been returned for this surface. Only one DC can be + * retrieved per surface. + */ +#define DDERR_DCALREADYCREATED MAKE_DDHRESULT( 620 ) + +/* + * The attempt to page lock a surface failed. + */ +#define DDERR_CANTPAGELOCK MAKE_DDHRESULT( 640 ) + +/* + * The attempt to page unlock a surface failed. + */ +#define DDERR_CANTPAGEUNLOCK MAKE_DDHRESULT( 660 ) + +/* + * An attempt was made to page unlock a surface with no outstanding page locks. + */ +#define DDERR_NOTPAGELOCKED MAKE_DDHRESULT( 680 ) + +/* + * An attempt was made to invoke an interface member of a DirectDraw object + * created by CoCreateInstance() before it was initialized. + */ +#define DDERR_NOTINITIALIZED CO_E_NOTINITIALIZED + +/* Alpha bit depth constants */ + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/WinQuake/dxsdk/SDK/INC/DINPUT.H b/WinQuake/dxsdk/SDK/INC/DINPUT.H index 331403c..ebbe1a2 100644 --- a/WinQuake/dxsdk/SDK/INC/DINPUT.H +++ b/WinQuake/dxsdk/SDK/INC/DINPUT.H @@ -1,873 +1,873 @@ -/**************************************************************************** - * - * Copyright (C) 1996 Microsoft Corporation. All Rights Reserved. - * - * File: dinput.h - * Content: DirectInput include file - * - ****************************************************************************/ - -#ifndef __DINPUT_INCLUDED__ -#define __DINPUT_INCLUDED__ - -#ifdef _WIN32 -#define COM_NO_WINDOWS_H -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define DIRECTINPUT_VERSION 0x0300 - -/**************************************************************************** - * - * Class IDs - * - ****************************************************************************/ - -DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(CLSID_DirectInputDevice,0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -/**************************************************************************** - * - * Interfaces - * - ****************************************************************************/ - -DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -DEFINE_GUID(IID_IDirectInputDeviceA,0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(IID_IDirectInputDeviceW,0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -/**************************************************************************** - * - * Predefined object types - * - ****************************************************************************/ - -DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_RAxis, 0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_UAxis, 0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_VAxis, 0xA36D02E5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -DEFINE_GUID(GUID_Button, 0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -/**************************************************************************** - * - * Predefined product GUIDs - * - ****************************************************************************/ - -DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); -DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); - -/**************************************************************************** - * - * Interfaces and Structures... - * - ****************************************************************************/ - -/**************************************************************************** - * - * IDirectInputDevice - * - ****************************************************************************/ - -#define DIDEVTYPE_DEVICE 1 -#define DIDEVTYPE_MOUSE 2 -#define DIDEVTYPE_KEYBOARD 3 -#define DIDEVTYPE_JOYSTICK 4 - -#define DIDEVTYPEMOUSE_UNKNOWN 1 -#define DIDEVTYPEMOUSE_TRADITIONAL 2 -#define DIDEVTYPEMOUSE_FINGERSTICK 3 -#define DIDEVTYPEMOUSE_TOUCHPAD 4 -#define DIDEVTYPEMOUSE_TRACKBALL 5 - -#define DIDEVTYPEKEYBOARD_PCXT 1 -#define DIDEVTYPEKEYBOARD_OLIVETTI 2 -#define DIDEVTYPEKEYBOARD_PCAT 3 -#define DIDEVTYPEKEYBOARD_PCENH 4 -#define DIDEVTYPEKEYBOARD_NOKIA1050 5 -#define DIDEVTYPEKEYBOARD_NOKIA9140 6 -#define DIDEVTYPEKEYBOARD_NEC98 7 -#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 -#define DIDEVTYPEKEYBOARD_NEC98106 9 -#define DIDEVTYPEKEYBOARD_JAPAN106 10 -#define DIDEVTYPEKEYBOARD_JAPANAX 11 -#define DIDEVTYPEKEYBOARD_J3100 12 - -#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) -#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) - -typedef struct _DIDEVCAPS { - DWORD dwSize; - DWORD dwFlags; - DWORD dwDevType; - DWORD dwAxes; - DWORD dwButtons; - DWORD dwPOVs; -} DIDEVCAPS, *LPDIDEVCAPS; - -#define DIDC_ATTACHED 0x00000001 -#define DIDC_POLLEDDEVICE 0x00000002 - -#define DIDFT_ALL 0x00000000 - -#define DIDFT_RELAXIS 0x00000001 -#define DIDFT_ABSAXIS 0x00000002 -#define DIDFT_AXIS 0x00000003 - -#define DIDFT_PSHBUTTON 0x00000004 -#define DIDFT_TGLBUTTON 0x00000008 -#define DIDFT_BUTTON 0x0000000C - -#define DIDFT_POV 0x00000010 - -#define DIDFT_ANYINSTANCE 0x0000FF00 -#define DIDFT_MAKEINSTANCE(n) ((BYTE)(n) << 8) -#define DIDFT_GETTYPE(n) LOBYTE(n) -#define DIDFT_GETINSTANCE(n) HIBYTE(n) - -typedef struct _DIOBJECTDATAFORMAT { - const GUID *pguid; - DWORD dwOfs; - DWORD dwType; - DWORD dwFlags; -} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; -typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; - -typedef struct _DIDATAFORMAT { - DWORD dwSize; - DWORD dwObjSize; - DWORD dwFlags; - DWORD dwDataSize; - DWORD dwNumObjs; - LPDIOBJECTDATAFORMAT rgodf; -} DIDATAFORMAT, *LPDIDATAFORMAT; -typedef const DIDATAFORMAT *LPCDIDATAFORMAT; - -#define DIDF_ABSAXIS 0x00000001 -#define DIDF_RELAXIS 0x00000002 - -extern const DIDATAFORMAT c_dfDIMouse; -extern const DIDATAFORMAT c_dfDIKeyboard; - -typedef struct DIDEVICEOBJECTINSTANCEA { - DWORD dwSize; - GUID guidType; - DWORD dwOfs; - DWORD dwType; - DWORD dwFlags; - CHAR tszName[MAX_PATH]; -} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; -typedef struct DIDEVICEOBJECTINSTANCEW { - DWORD dwSize; - GUID guidType; - DWORD dwOfs; - DWORD dwType; - DWORD dwFlags; - WCHAR tszName[MAX_PATH]; -} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; -#ifdef UNICODE -typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE; -typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE; -#else -typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE; -typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE; -#endif // UNICODE -typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; -typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; -typedef const DIDEVICEOBJECTINSTANCE *LPCDIDEVICEOBJECTINSTANCE; - -typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID); -typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID); -#ifdef UNICODE -#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKW -#else -#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKA -#endif // !UNICODE - -typedef struct DIPROPHEADER { - DWORD dwSize; - DWORD dwHeaderSize; - DWORD dwObj; - DWORD dwHow; -} DIPROPHEADER, *LPDIPROPHEADER; -typedef const DIPROPHEADER *LPCDIPROPHEADER; - -#define DIPH_DEVICE 0 -#define DIPH_BYOFFSET 1 -#define DIPH_BYID 2 - -typedef struct DIPROPDWORD { - DIPROPHEADER diph; - DWORD dwData; -} DIPROPDWORD, *LPDIPROPDWORD; -typedef const DIPROPDWORD *LPCDIPROPDWORD; - -typedef struct DIPROPRANGE { - DIPROPHEADER diph; - LONG lMin; - LONG lMax; -} DIPROPRANGE, *LPDIPROPRANGE; -typedef const DIPROPRANGE *LPCDIPROPRANGE; - -#define DIPROPRANGE_NOMIN ((LONG)0x80000000) -#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) - -#ifdef __cplusplus -#define MAKEDIPROP(prop) (*(const GUID *)(prop)) -#else -#define MAKEDIPROP(prop) ((REFGUID)(prop)) -#endif - -#define DIPROP_BUFFERSIZE MAKEDIPROP(1) - -#define DIPROP_AXISMODE MAKEDIPROP(2) - -#define DIPROPAXISMODE_ABS 0 -#define DIPROPAXISMODE_REL 1 - -#define DIPROP_GRANULARITY MAKEDIPROP(3) - -#define DIPROP_RANGE MAKEDIPROP(4) - -typedef struct DIDEVICEOBJECTDATA { - DWORD dwOfs; - DWORD dwData; - DWORD dwTimeStamp; - DWORD dwSequence; -} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; - -#define DIGDD_PEEK 0x00000001 - -#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \ - ((int)((dwSequence1) - (dwSequence2)) cmp 0) - -#define DISCL_EXCLUSIVE 0x00000001 -#define DISCL_NONEXCLUSIVE 0x00000002 -#define DISCL_FOREGROUND 0x00000004 -#define DISCL_BACKGROUND 0x00000008 - -typedef struct DIDEVICEINSTANCEA { - DWORD dwSize; - GUID guidInstance; - GUID guidProduct; - DWORD dwDevType; - CHAR tszInstanceName[MAX_PATH]; - CHAR tszProductName[MAX_PATH]; -} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; -typedef struct DIDEVICEINSTANCEW { - DWORD dwSize; - GUID guidInstance; - GUID guidProduct; - DWORD dwDevType; - WCHAR tszInstanceName[MAX_PATH]; - WCHAR tszProductName[MAX_PATH]; -} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; -#ifdef UNICODE -typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; -typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE; -#else -typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; -typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE; -#endif // UNICODE -typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; -typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; -typedef const DIDEVICEINSTANCE *LPCDIDEVICEINSTANCE; - -#undef INTERFACE -#define INTERFACE IDirectInputDeviceW - -DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - /*** IDirectInputDeviceW methods ***/ - STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; - STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; - STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; - STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; - STDMETHOD(Acquire)(THIS) PURE; - STDMETHOD(Unacquire)(THIS) PURE; - STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; - STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; - STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; - STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; - STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; - STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; -}; - -typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; - -#undef INTERFACE -#define INTERFACE IDirectInputDeviceA - -DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - /*** IDirectInputDeviceA methods ***/ - STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; - STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; - STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; - STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; - STDMETHOD(Acquire)(THIS) PURE; - STDMETHOD(Unacquire)(THIS) PURE; - STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; - STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; - STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; - STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; - STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; - STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; -}; - -typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; - -#ifdef UNICODE -#define IID_IDirectInputDevice IID_IDirectInputDeviceW -#define IDirectInputDevice IDirectInputDeviceW -#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl -#else -#define IID_IDirectInputDevice IID_IDirectInputDeviceA -#define IDirectInputDevice IDirectInputDeviceA -#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl -#endif -typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) -#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) -#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) -#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) -#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) -#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) -#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) -#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) -#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) -#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) -#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) -#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) -#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) -#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) -#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) -#endif - -/**************************************************************************** - * - * Mouse - * - ****************************************************************************/ - -typedef struct _DIMOUSESTATE { - LONG lX; - LONG lY; - LONG lZ; - BYTE rgbButtons[4]; -} DIMOUSESTATE, *LPDIMOUSESTATE; - -#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) -#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) -#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) -#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) -#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) -#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) -#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) - -/**************************************************************************** - * - * Keyboard - * - ****************************************************************************/ - -/**************************************************************************** - * - * DirectInput keyboard scan codes - * - ****************************************************************************/ - -#define DIK_ESCAPE 0x01 -#define DIK_1 0x02 -#define DIK_2 0x03 -#define DIK_3 0x04 -#define DIK_4 0x05 -#define DIK_5 0x06 -#define DIK_6 0x07 -#define DIK_7 0x08 -#define DIK_8 0x09 -#define DIK_9 0x0A -#define DIK_0 0x0B -#define DIK_MINUS 0x0C /* - on main keyboard */ -#define DIK_EQUALS 0x0D -#define DIK_BACK 0x0E /* backspace */ -#define DIK_TAB 0x0F -#define DIK_Q 0x10 -#define DIK_W 0x11 -#define DIK_E 0x12 -#define DIK_R 0x13 -#define DIK_T 0x14 -#define DIK_Y 0x15 -#define DIK_U 0x16 -#define DIK_I 0x17 -#define DIK_O 0x18 -#define DIK_P 0x19 -#define DIK_LBRACKET 0x1A -#define DIK_RBRACKET 0x1B -#define DIK_RETURN 0x1C /* Enter on main keyboard */ -#define DIK_LCONTROL 0x1D -#define DIK_A 0x1E -#define DIK_S 0x1F -#define DIK_D 0x20 -#define DIK_F 0x21 -#define DIK_G 0x22 -#define DIK_H 0x23 -#define DIK_J 0x24 -#define DIK_K 0x25 -#define DIK_L 0x26 -#define DIK_SEMICOLON 0x27 -#define DIK_APOSTROPHE 0x28 -#define DIK_GRAVE 0x29 /* accent grave */ -#define DIK_LSHIFT 0x2A -#define DIK_BACKSLASH 0x2B -#define DIK_Z 0x2C -#define DIK_X 0x2D -#define DIK_C 0x2E -#define DIK_V 0x2F -#define DIK_B 0x30 -#define DIK_N 0x31 -#define DIK_M 0x32 -#define DIK_COMMA 0x33 -#define DIK_PERIOD 0x34 /* . on main keyboard */ -#define DIK_SLASH 0x35 /* / on main keyboard */ -#define DIK_RSHIFT 0x36 -#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ -#define DIK_LMENU 0x38 /* left Alt */ -#define DIK_SPACE 0x39 -#define DIK_CAPITAL 0x3A -#define DIK_F1 0x3B -#define DIK_F2 0x3C -#define DIK_F3 0x3D -#define DIK_F4 0x3E -#define DIK_F5 0x3F -#define DIK_F6 0x40 -#define DIK_F7 0x41 -#define DIK_F8 0x42 -#define DIK_F9 0x43 -#define DIK_F10 0x44 -#define DIK_NUMLOCK 0x45 -#define DIK_SCROLL 0x46 /* Scroll Lock */ -#define DIK_NUMPAD7 0x47 -#define DIK_NUMPAD8 0x48 -#define DIK_NUMPAD9 0x49 -#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ -#define DIK_NUMPAD4 0x4B -#define DIK_NUMPAD5 0x4C -#define DIK_NUMPAD6 0x4D -#define DIK_ADD 0x4E /* + on numeric keypad */ -#define DIK_NUMPAD1 0x4F -#define DIK_NUMPAD2 0x50 -#define DIK_NUMPAD3 0x51 -#define DIK_NUMPAD0 0x52 -#define DIK_DECIMAL 0x53 /* . on numeric keypad */ -#define DIK_F11 0x57 -#define DIK_F12 0x58 - -#define DIK_F13 0x64 /* (NEC PC98) */ -#define DIK_F14 0x65 /* (NEC PC98) */ -#define DIK_F15 0x66 /* (NEC PC98) */ - -#define DIK_KANA 0x70 /* (Japanese keyboard) */ -#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ -#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ -#define DIK_YEN 0x7D /* (Japanese keyboard) */ -#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ -#define DIK_CIRCUMFLEX 0x90 /* (Japanese keyboard) */ -#define DIK_AT 0x91 /* (NEC PC98) */ -#define DIK_COLON 0x92 /* (NEC PC98) */ -#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ -#define DIK_KANJI 0x94 /* (Japanese keyboard) */ -#define DIK_STOP 0x95 /* (NEC PC98) */ -#define DIK_AX 0x96 /* (Japan AX) */ -#define DIK_UNLABELED 0x97 /* (J3100) */ -#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ -#define DIK_RCONTROL 0x9D -#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ -#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ -#define DIK_SYSRQ 0xB7 -#define DIK_RMENU 0xB8 /* right Alt */ -#define DIK_HOME 0xC7 /* Home on arrow keypad */ -#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ -#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ -#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ -#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ -#define DIK_END 0xCF /* End on arrow keypad */ -#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ -#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ -#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ -#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ -#define DIK_LWIN 0xDB /* Left Windows key */ -#define DIK_RWIN 0xDC /* Right Windows key */ -#define DIK_APPS 0xDD /* AppMenu key */ - -/* - * Alternate names for keys, to facilitate transition from DOS. - */ -#define DIK_BACKSPACE DIK_BACK /* backspace */ -#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ -#define DIK_LALT DIK_LMENU /* left Alt */ -#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ -#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ -#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ -#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ -#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ -#define DIK_RALT DIK_RMENU /* right Alt */ -#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ -#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ -#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ -#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ -#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ -#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ - -/**************************************************************************** - * - * IDirectInput - * - ****************************************************************************/ - -#define DIENUM_STOP 0 -#define DIENUM_CONTINUE 1 - -typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID); -typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID); -#ifdef UNICODE -#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKW -#else -#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKA -#endif // !UNICODE - -#define DIEDFL_ALLDEVICES 0x00000000 -#define DIEDFL_ATTACHEDONLY 0x00000001 - -#undef INTERFACE -#define INTERFACE IDirectInputW - -DECLARE_INTERFACE_(IDirectInputW, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - /*** IDirectInputW methods ***/ - STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; - STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; - STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; - STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; -}; - -typedef struct IDirectInputW *LPDIRECTINPUTW; - -#undef INTERFACE -#define INTERFACE IDirectInputA - -DECLARE_INTERFACE_(IDirectInputA, IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - - /*** IDirectInputA methods ***/ - STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; - STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; - STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; - STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; - STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; -}; - -typedef struct IDirectInputA *LPDIRECTINPUTA; - -#ifdef UNICODE -#define IID_IDirectInput IID_IDirectInputW -#define IDirectInput IDirectInputW -#define IDirectInputVtbl IDirectInputWVtbl -#else -#define IID_IDirectInput IID_IDirectInputA -#define IDirectInput IDirectInputA -#define IDirectInputVtbl IDirectInputAVtbl -#endif -typedef struct IDirectInput *LPDIRECTINPUT; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) -#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) -#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) -#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) -#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) -#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#endif - -extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter); -extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter); -#ifdef UNICODE -#define DirectInputCreate DirectInputCreateW -#else -#define DirectInputCreate DirectInputCreateA -#endif // !UNICODE - -/**************************************************************************** - * - * Return Codes - * - ****************************************************************************/ - -/* - * The operation completed successfully. - */ -#define DI_OK S_OK - -/* - * The device exists but is not currently attached. - */ -#define DI_NOTATTACHED S_FALSE - -/* - * The device buffer overflowed; some input was lost. - */ -#define DI_BUFFEROVERFLOW S_FALSE - -/* - * The change in device properties had no effect. - */ -#define DI_PROPNOEFFECT S_FALSE - -/* - * The device is a polled device. As a result, device buffering - * will not collect any data and event notifications will not be - * signalled until GetDeviceState is called. - */ -#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) - -/* - * The application requires a newer version of DirectInput. - */ -#define DIERR_OLDDIRECTINPUTVERSION \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) - -/* - * The application was written for an unsupported prerelease version - * of DirectInput. - */ -#define DIERR_BETADIRECTINPUTVERSION \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) - -/* - * The object could not be created due to an incompatible driver version - * or mismatched or incomplete driver components. - */ -#define DIERR_BADDRIVERVER \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) - -/* - * The device or device instance is not registered with DirectInput. - */ -#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG - -/* - * The requested object does not exist. - */ -#define DIERR_OBJECTNOTFOUND \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) - -/* - * An invalid parameter was passed to the returning function, - * or the object was not in a state that admitted the function - * to be called. - */ -#define DIERR_INVALIDPARAM E_INVALIDARG - -/* - * The specified interface is not supported by the object - */ -#define DIERR_NOINTERFACE E_NOINTERFACE - -/* - * An undetermined error occured inside the DInput subsystem - */ -#define DIERR_GENERIC E_FAIL - -/* - * The DInput subsystem couldn't allocate sufficient memory to complete the - * caller's request. - */ -#define DIERR_OUTOFMEMORY E_OUTOFMEMORY - -/* - * The function called is not supported at this time - */ -#define DIERR_UNSUPPORTED E_NOTIMPL - -/* - * This object has not been initialized - */ -#define DIERR_NOTINITIALIZED \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) - -/* - * This object is already initialized - */ -#define DIERR_ALREADYINITIALIZED \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) - -/* - * This object does not support aggregation - */ -#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION - -/* - * Another app has a higher priority level, preventing this call from - * succeeding. - */ -#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED - -/* - * Access to the input device has been lost. It must be re-acquired. - */ -#define DIERR_INPUTLOST \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) - -/* - * The operation cannot be performed while the device is acquired. - */ -#define DIERR_ACQUIRED \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) - -/* - * The operation cannot be performed unless the device is acquired. - */ -#define DIERR_NOTACQUIRED \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) - -/* - * The specified property cannot be changed. - */ -#define DIERR_READONLY E_ACCESSDENIED - -/* - * The device already has an event notification associated with it. - */ -#define DIERR_HANDLEEXISTS E_ACCESSDENIED - -/* - * Data is not yet available. - */ -#ifndef E_PENDING -#define E_PENDING 0x80070007L -#endif - -#ifdef __cplusplus -}; -#endif - -#endif /* __DINPUT_INCLUDED__ */ - -/**************************************************************************** - * - * Definitions for non-IDirectInput (VJoyD) features defined more recently - * than the current sdk files - * - ****************************************************************************/ - -#ifdef _INC_MMSYSTEM -#ifndef MMNOJOY - -#ifndef __VJOYDX_INCLUDED__ -#define __VJOYDX_INCLUDED__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure - * contains mini-driver specific data to be passed by VJoyD to the mini- - * driver instead of doing a poll. - */ -#define JOY_PASSDRIVERDATA 0x10000000l - -/* - * Informs the joystick driver that the configuration has been changed - * and should be reloaded from the registery. - * dwFlags is reserved and should be set to zero - */ -WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags ); - -/* - * Hardware Setting indicating that the device is a headtracker - */ -#define JOY_HWS_ISHEADTRACKER 0x02000000l - -/* - * Hardware Setting indicating that the VxD is used to replace - * the standard analog polling - */ -#define JOY_HWS_ISGAMEPORTDRIVER 0x04000000l - -#ifdef __cplusplus -}; -#endif - -#endif /* __VJOYDX_INCLUDED__ */ - -#endif /* not MMNOJOY */ -#endif /* _INC_MMSYSTEM */ - -/**************************************************************************** - * - * Definitions for non-IDirectInput (VJoyD) features defined more recently - * than the current ddk files - * - ****************************************************************************/ - -#ifdef _INC_MMDDK -#ifndef MMNOJOYDEV - -#ifndef __VJOYDXD_INCLUDED__ -#define __VJOYDXD_INCLUDED__ -/* - * Poll type in which the do_other field of the JOYOEMPOLLDATA - * structure contains mini-driver specific data passed from an app. - */ -#define JOY_OEMPOLL_PASSDRIVERDATA 7 - -#endif /* __VJOYDXD_INCLUDED__ */ - -#endif /* not MMNOJOYDEV */ -#endif /* _INC_MMDDK */ +/**************************************************************************** + * + * Copyright (C) 1996 Microsoft Corporation. All Rights Reserved. + * + * File: dinput.h + * Content: DirectInput include file + * + ****************************************************************************/ + +#ifndef __DINPUT_INCLUDED__ +#define __DINPUT_INCLUDED__ + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define DIRECTINPUT_VERSION 0x0300 + +/**************************************************************************** + * + * Class IDs + * + ****************************************************************************/ + +DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice,0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Interfaces + * + ****************************************************************************/ + +DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(IID_IDirectInputDeviceA,0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDeviceW,0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined object types + * + ****************************************************************************/ + +DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RAxis, 0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_UAxis, 0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_VAxis, 0xA36D02E5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_Button, 0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined product GUIDs + * + ****************************************************************************/ + +DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Interfaces and Structures... + * + ****************************************************************************/ + +/**************************************************************************** + * + * IDirectInputDevice + * + ****************************************************************************/ + +#define DIDEVTYPE_DEVICE 1 +#define DIDEVTYPE_MOUSE 2 +#define DIDEVTYPE_KEYBOARD 3 +#define DIDEVTYPE_JOYSTICK 4 + +#define DIDEVTYPEMOUSE_UNKNOWN 1 +#define DIDEVTYPEMOUSE_TRADITIONAL 2 +#define DIDEVTYPEMOUSE_FINGERSTICK 3 +#define DIDEVTYPEMOUSE_TOUCHPAD 4 +#define DIDEVTYPEMOUSE_TRACKBALL 5 + +#define DIDEVTYPEKEYBOARD_PCXT 1 +#define DIDEVTYPEKEYBOARD_OLIVETTI 2 +#define DIDEVTYPEKEYBOARD_PCAT 3 +#define DIDEVTYPEKEYBOARD_PCENH 4 +#define DIDEVTYPEKEYBOARD_NOKIA1050 5 +#define DIDEVTYPEKEYBOARD_NOKIA9140 6 +#define DIDEVTYPEKEYBOARD_NEC98 7 +#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DIDEVTYPEKEYBOARD_NEC98106 9 +#define DIDEVTYPEKEYBOARD_JAPAN106 10 +#define DIDEVTYPEKEYBOARD_JAPANAX 11 +#define DIDEVTYPEKEYBOARD_J3100 12 + +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + +typedef struct _DIDEVCAPS { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +} DIDEVCAPS, *LPDIDEVCAPS; + +#define DIDC_ATTACHED 0x00000001 +#define DIDC_POLLEDDEVICE 0x00000002 + +#define DIDFT_ALL 0x00000000 + +#define DIDFT_RELAXIS 0x00000001 +#define DIDFT_ABSAXIS 0x00000002 +#define DIDFT_AXIS 0x00000003 + +#define DIDFT_PSHBUTTON 0x00000004 +#define DIDFT_TGLBUTTON 0x00000008 +#define DIDFT_BUTTON 0x0000000C + +#define DIDFT_POV 0x00000010 + +#define DIDFT_ANYINSTANCE 0x0000FF00 +#define DIDFT_MAKEINSTANCE(n) ((BYTE)(n) << 8) +#define DIDFT_GETTYPE(n) LOBYTE(n) +#define DIDFT_GETINSTANCE(n) HIBYTE(n) + +typedef struct _DIOBJECTDATAFORMAT { + const GUID *pguid; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; +} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; +typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; + +typedef struct _DIDATAFORMAT { + DWORD dwSize; + DWORD dwObjSize; + DWORD dwFlags; + DWORD dwDataSize; + DWORD dwNumObjs; + LPDIOBJECTDATAFORMAT rgodf; +} DIDATAFORMAT, *LPDIDATAFORMAT; +typedef const DIDATAFORMAT *LPCDIDATAFORMAT; + +#define DIDF_ABSAXIS 0x00000001 +#define DIDF_RELAXIS 0x00000002 + +extern const DIDATAFORMAT c_dfDIMouse; +extern const DIDATAFORMAT c_dfDIKeyboard; + +typedef struct DIDEVICEOBJECTINSTANCEA { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; +typedef struct DIDEVICEOBJECTINSTANCEW { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE; +#else +typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE; +#endif // UNICODE +typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; +typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; +typedef const DIDEVICEOBJECTINSTANCE *LPCDIDEVICEOBJECTINSTANCE; + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKW +#else +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKA +#endif // !UNICODE + +typedef struct DIPROPHEADER { + DWORD dwSize; + DWORD dwHeaderSize; + DWORD dwObj; + DWORD dwHow; +} DIPROPHEADER, *LPDIPROPHEADER; +typedef const DIPROPHEADER *LPCDIPROPHEADER; + +#define DIPH_DEVICE 0 +#define DIPH_BYOFFSET 1 +#define DIPH_BYID 2 + +typedef struct DIPROPDWORD { + DIPROPHEADER diph; + DWORD dwData; +} DIPROPDWORD, *LPDIPROPDWORD; +typedef const DIPROPDWORD *LPCDIPROPDWORD; + +typedef struct DIPROPRANGE { + DIPROPHEADER diph; + LONG lMin; + LONG lMax; +} DIPROPRANGE, *LPDIPROPRANGE; +typedef const DIPROPRANGE *LPCDIPROPRANGE; + +#define DIPROPRANGE_NOMIN ((LONG)0x80000000) +#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) + +#ifdef __cplusplus +#define MAKEDIPROP(prop) (*(const GUID *)(prop)) +#else +#define MAKEDIPROP(prop) ((REFGUID)(prop)) +#endif + +#define DIPROP_BUFFERSIZE MAKEDIPROP(1) + +#define DIPROP_AXISMODE MAKEDIPROP(2) + +#define DIPROPAXISMODE_ABS 0 +#define DIPROPAXISMODE_REL 1 + +#define DIPROP_GRANULARITY MAKEDIPROP(3) + +#define DIPROP_RANGE MAKEDIPROP(4) + +typedef struct DIDEVICEOBJECTDATA { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; + +#define DIGDD_PEEK 0x00000001 + +#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \ + ((int)((dwSequence1) - (dwSequence2)) cmp 0) + +#define DISCL_EXCLUSIVE 0x00000001 +#define DISCL_NONEXCLUSIVE 0x00000002 +#define DISCL_FOREGROUND 0x00000004 +#define DISCL_BACKGROUND 0x00000008 + +typedef struct DIDEVICEINSTANCEA { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; +typedef struct DIDEVICEINSTANCEW { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE; +#else +typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE; +#endif // UNICODE +typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; +typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; +typedef const DIDEVICEINSTANCE *LPCDIDEVICEINSTANCE; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceW + +DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceA + +DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; + +#ifdef UNICODE +#define IID_IDirectInputDevice IID_IDirectInputDeviceW +#define IDirectInputDevice IDirectInputDeviceW +#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl +#else +#define IID_IDirectInputDevice IID_IDirectInputDeviceA +#define IDirectInputDevice IDirectInputDeviceA +#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl +#endif +typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#endif + +/**************************************************************************** + * + * Mouse + * + ****************************************************************************/ + +typedef struct _DIMOUSESTATE { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[4]; +} DIMOUSESTATE, *LPDIMOUSESTATE; + +#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) +#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) +#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) +#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) +#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) +#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) +#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) + +/**************************************************************************** + * + * Keyboard + * + ****************************************************************************/ + +/**************************************************************************** + * + * DirectInput keyboard scan codes + * + ****************************************************************************/ + +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 + +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ + +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_CIRCUMFLEX 0x90 /* (Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ + +/* + * Alternate names for keys, to facilitate transition from DOS. + */ +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +/**************************************************************************** + * + * IDirectInput + * + ****************************************************************************/ + +#define DIENUM_STOP 0 +#define DIENUM_CONTINUE 1 + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKW +#else +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKA +#endif // !UNICODE + +#define DIEDFL_ALLDEVICES 0x00000000 +#define DIEDFL_ATTACHEDONLY 0x00000001 + +#undef INTERFACE +#define INTERFACE IDirectInputW + +DECLARE_INTERFACE_(IDirectInputW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputW *LPDIRECTINPUTW; + +#undef INTERFACE +#define INTERFACE IDirectInputA + +DECLARE_INTERFACE_(IDirectInputA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputA *LPDIRECTINPUTA; + +#ifdef UNICODE +#define IID_IDirectInput IID_IDirectInputW +#define IDirectInput IDirectInputW +#define IDirectInputVtbl IDirectInputWVtbl +#else +#define IID_IDirectInput IID_IDirectInputA +#define IDirectInput IDirectInputA +#define IDirectInputVtbl IDirectInputAVtbl +#endif +typedef struct IDirectInput *LPDIRECTINPUT; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#endif + +extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter); +extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter); +#ifdef UNICODE +#define DirectInputCreate DirectInputCreateW +#else +#define DirectInputCreate DirectInputCreateA +#endif // !UNICODE + +/**************************************************************************** + * + * Return Codes + * + ****************************************************************************/ + +/* + * The operation completed successfully. + */ +#define DI_OK S_OK + +/* + * The device exists but is not currently attached. + */ +#define DI_NOTATTACHED S_FALSE + +/* + * The device buffer overflowed; some input was lost. + */ +#define DI_BUFFEROVERFLOW S_FALSE + +/* + * The change in device properties had no effect. + */ +#define DI_PROPNOEFFECT S_FALSE + +/* + * The device is a polled device. As a result, device buffering + * will not collect any data and event notifications will not be + * signalled until GetDeviceState is called. + */ +#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) + +/* + * The application requires a newer version of DirectInput. + */ +#define DIERR_OLDDIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) + +/* + * The application was written for an unsupported prerelease version + * of DirectInput. + */ +#define DIERR_BETADIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) + +/* + * The object could not be created due to an incompatible driver version + * or mismatched or incomplete driver components. + */ +#define DIERR_BADDRIVERVER \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) + +/* + * The device or device instance is not registered with DirectInput. + */ +#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/* + * The requested object does not exist. + */ +#define DIERR_OBJECTNOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) + +/* + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define DIERR_INVALIDPARAM E_INVALIDARG + +/* + * The specified interface is not supported by the object + */ +#define DIERR_NOINTERFACE E_NOINTERFACE + +/* + * An undetermined error occured inside the DInput subsystem + */ +#define DIERR_GENERIC E_FAIL + +/* + * The DInput subsystem couldn't allocate sufficient memory to complete the + * caller's request. + */ +#define DIERR_OUTOFMEMORY E_OUTOFMEMORY + +/* + * The function called is not supported at this time + */ +#define DIERR_UNSUPPORTED E_NOTIMPL + +/* + * This object has not been initialized + */ +#define DIERR_NOTINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) + +/* + * This object is already initialized + */ +#define DIERR_ALREADYINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) + +/* + * This object does not support aggregation + */ +#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION + +/* + * Another app has a higher priority level, preventing this call from + * succeeding. + */ +#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED + +/* + * Access to the input device has been lost. It must be re-acquired. + */ +#define DIERR_INPUTLOST \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) + +/* + * The operation cannot be performed while the device is acquired. + */ +#define DIERR_ACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) + +/* + * The operation cannot be performed unless the device is acquired. + */ +#define DIERR_NOTACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) + +/* + * The specified property cannot be changed. + */ +#define DIERR_READONLY E_ACCESSDENIED + +/* + * The device already has an event notification associated with it. + */ +#define DIERR_HANDLEEXISTS E_ACCESSDENIED + +/* + * Data is not yet available. + */ +#ifndef E_PENDING +#define E_PENDING 0x80070007L +#endif + +#ifdef __cplusplus +}; +#endif + +#endif /* __DINPUT_INCLUDED__ */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current sdk files + * + ****************************************************************************/ + +#ifdef _INC_MMSYSTEM +#ifndef MMNOJOY + +#ifndef __VJOYDX_INCLUDED__ +#define __VJOYDX_INCLUDED__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure + * contains mini-driver specific data to be passed by VJoyD to the mini- + * driver instead of doing a poll. + */ +#define JOY_PASSDRIVERDATA 0x10000000l + +/* + * Informs the joystick driver that the configuration has been changed + * and should be reloaded from the registery. + * dwFlags is reserved and should be set to zero + */ +WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags ); + +/* + * Hardware Setting indicating that the device is a headtracker + */ +#define JOY_HWS_ISHEADTRACKER 0x02000000l + +/* + * Hardware Setting indicating that the VxD is used to replace + * the standard analog polling + */ +#define JOY_HWS_ISGAMEPORTDRIVER 0x04000000l + +#ifdef __cplusplus +}; +#endif + +#endif /* __VJOYDX_INCLUDED__ */ + +#endif /* not MMNOJOY */ +#endif /* _INC_MMSYSTEM */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current ddk files + * + ****************************************************************************/ + +#ifdef _INC_MMDDK +#ifndef MMNOJOYDEV + +#ifndef __VJOYDXD_INCLUDED__ +#define __VJOYDXD_INCLUDED__ +/* + * Poll type in which the do_other field of the JOYOEMPOLLDATA + * structure contains mini-driver specific data passed from an app. + */ +#define JOY_OEMPOLL_PASSDRIVERDATA 7 + +#endif /* __VJOYDXD_INCLUDED__ */ + +#endif /* not MMNOJOYDEV */ +#endif /* _INC_MMDDK */ diff --git a/WinQuake/dxsdk/SDK/INC/DPLAY.H b/WinQuake/dxsdk/SDK/INC/DPLAY.H index b396bc5..5501c25 100644 --- a/WinQuake/dxsdk/SDK/INC/DPLAY.H +++ b/WinQuake/dxsdk/SDK/INC/DPLAY.H @@ -1,308 +1,308 @@ -/*==========================================================================; - * - * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved. - * - * File: dplay.h - * Content: DirectPlay include file - * - ***************************************************************************/ - -#ifndef __DPLAY_INCLUDED__ -#define __DPLAY_INCLUDED__ -#ifdef _WIN32 -/* for DECLARE_INTERFACE and HRESULT. */ -#include -#endif - -#define _FACDP 0x877 -#define MAKE_DPHRESULT( code ) MAKE_HRESULT( 1, _FACDP, code ) - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma pack(push, 1) - - -/*============================================================================ - * - * DirectPlay Structures - * - * Various structures used to invoke DirectPlay. - * - *==========================================================================*/ - -#ifdef __cplusplus -/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ -struct IDirectPlay; -typedef struct IDirectPlay FAR *LPDIRECTPLAY; -#else -typedef struct IDirectPlay FAR *LPDIRECTPLAY; -#endif - -typedef DWORD DPID, FAR *LPDPID; - -typedef struct _DPCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwMaxBufferSize; - DWORD dwMaxQueueSize; // Function of DPlay, not SP. - DWORD dwMaxPlayers; - DWORD dwHundredBaud; // 24 is 2400, 96 is 9600, etc. - DWORD dwLatency; -} DPCAPS; - -typedef DPCAPS FAR *LPDPCAPS; - -#define DPLONGNAMELEN 52 -#define DPSHORTNAMELEN 20 -#define DPSESSIONNAMELEN 32 -#define DPPASSWORDLEN 16 -#define DPUSERRESERVED 16 - -typedef struct -{ - DWORD dwSize; - GUID guidSession; // Id for Game. Null is all games. - DWORD dwSession; // session identifier - DWORD dwMaxPlayers; // Maximum players allowed in game. - DWORD dwCurrentPlayers; // Current players in Game. - DWORD dwFlags; // DPOPEN_* flags - char szSessionName[DPSESSIONNAMELEN];// Human readable name for Game - char szUserField[DPUSERRESERVED]; - DWORD dwReserved1; // Reserved for future MS use. - char szPassword[DPPASSWORDLEN]; // Password to be allowed into game. - DWORD dwReserved2; // Reserved for future MS use. - DWORD dwUser1; - DWORD dwUser2; - DWORD dwUser3; - DWORD dwUser4; -} DPSESSIONDESC; -typedef DPSESSIONDESC FAR *LPDPSESSIONDESC; - - -/* - * Create API - */ -typedef BOOL (FAR PASCAL * LPDPENUMDPCALLBACK)( - LPGUID lpSPGuid, - LPSTR lpFriendlyName, - DWORD dwMajorVersion, - DWORD dwMinorVersion, - LPVOID lpContext); - -typedef BOOL (FAR PASCAL * LPDPENUMSESSIONSCALLBACK)( - LPDPSESSIONDESC lpDPSGameDesc, - LPVOID lpContext, - LPDWORD lpdwTimeOut, - DWORD dwFlags); - - - -extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY FAR *lplpDP, IUnknown FAR *pUnk); -extern HRESULT WINAPI DirectPlayEnumerate( LPDPENUMDPCALLBACK, LPVOID ); - - -/* Player enumeration callback prototype */ -typedef BOOL (FAR PASCAL *LPDPENUMPLAYERSCALLBACK)( - DPID dpId, - LPSTR lpFriendlyName, - LPSTR lpFormalName, - DWORD dwFlags, - LPVOID lpContext ); - -/* - * IDirectPlay - */ -#undef INTERFACE -#define INTERFACE IDirectPlay -#ifdef _WIN32 -DECLARE_INTERFACE_( IDirectPlay, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectPlay methods ***/ - STDMETHOD(AddPlayerToGroup) (THIS_ DPID, DPID) PURE; - STDMETHOD(Close) (THIS) PURE; - STDMETHOD(CreatePlayer) (THIS_ LPDPID,LPSTR,LPSTR,LPHANDLE) PURE; - STDMETHOD(CreateGroup) (THIS_ LPDPID,LPSTR,LPSTR) PURE; - STDMETHOD(DeletePlayerFromGroup)(THIS_ DPID,DPID) PURE; - STDMETHOD(DestroyPlayer) (THIS_ DPID) PURE; - STDMETHOD(DestroyGroup) (THIS_ DPID) PURE; - STDMETHOD(EnableNewPlayers) (THIS_ BOOL) PURE; - STDMETHOD(EnumGroupPlayers) (THIS_ DPID, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; - STDMETHOD(EnumGroups) (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; - STDMETHOD(EnumPlayers) (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; - STDMETHOD(EnumSessions) (THIS_ LPDPSESSIONDESC,DWORD,LPDPENUMSESSIONSCALLBACK,LPVOID,DWORD) PURE; - STDMETHOD(GetCaps) (THIS_ LPDPCAPS) PURE; - STDMETHOD(GetMessageCount) (THIS_ DPID, LPDWORD) PURE; - STDMETHOD(GetPlayerCaps) (THIS_ DPID, LPDPCAPS) PURE; - STDMETHOD(GetPlayerName) (THIS_ DPID,LPSTR,LPDWORD,LPSTR,LPDWORD) PURE; - STDMETHOD(Initialize) (THIS_ LPGUID) PURE; - STDMETHOD(Open) (THIS_ LPDPSESSIONDESC) PURE; - STDMETHOD(Receive) (THIS_ LPDPID,LPDPID,DWORD,LPVOID,LPDWORD) PURE; - STDMETHOD(SaveSession) (THIS_ LPSTR) PURE; - STDMETHOD(Send) (THIS_ DPID, DPID, DWORD, LPVOID, DWORD) PURE; - STDMETHOD(SetPlayerName) (THIS_ DPID,LPSTR,LPSTR) PURE; -}; -#endif - - - - -/**************************************************************************** - * - * DIRECTPLAY ERRORS - * - * Errors are represented by negative values and cannot be combined. - * - ****************************************************************************/ -#define DP_OK 0 -#define DPERR_ALREADYINITIALIZED MAKE_DPHRESULT( 5 ) -#define DPERR_ACCESSDENIED MAKE_DPHRESULT( 10 ) -#define DPERR_ACTIVEPLAYERS MAKE_DPHRESULT( 20 ) -#define DPERR_BUFFERTOOSMALL MAKE_DPHRESULT( 30 ) -#define DPERR_CANTADDPLAYER MAKE_DPHRESULT( 40 ) -#define DPERR_CANTCREATEGROUP MAKE_DPHRESULT( 50 ) -#define DPERR_CANTCREATEPLAYER MAKE_DPHRESULT( 60 ) -#define DPERR_CANTCREATESESSION MAKE_DPHRESULT( 70 ) -#define DPERR_CAPSNOTAVAILABLEYET MAKE_DPHRESULT( 80 ) -#define DPERR_EXCEPTION MAKE_DPHRESULT( 90 ) -#define DPERR_GENERIC E_FAIL - -#define DPERR_INVALIDFLAGS MAKE_DPHRESULT( 120 ) -#define DPERR_INVALIDOBJECT MAKE_DPHRESULT( 130 ) -#define DPERR_INVALIDPARAM E_INVALIDARG -#define DPERR_INVALIDPARAMS DPERR_INVALIDPARAM -#define DPERR_INVALIDPLAYER MAKE_DPHRESULT( 150 ) -#define DPERR_NOCAPS MAKE_DPHRESULT( 160 ) -#define DPERR_NOCONNECTION MAKE_DPHRESULT( 170 ) -#define DPERR_NOMEMORY E_OUTOFMEMORY -#define DPERR_OUTOFMEMORY DPERR_NOMEMORY -#define DPERR_NOMESSAGES MAKE_DPHRESULT( 190 ) -#define DPERR_NONAMESERVERFOUND MAKE_DPHRESULT( 200 ) -#define DPERR_NOPLAYERS MAKE_DPHRESULT( 210 ) -#define DPERR_NOSESSIONS MAKE_DPHRESULT( 220 ) -#define DPERR_SENDTOOBIG MAKE_DPHRESULT( 230 ) -#define DPERR_TIMEOUT MAKE_DPHRESULT( 240 ) -#define DPERR_UNAVAILABLE MAKE_DPHRESULT( 250 ) -#define DPERR_UNSUPPORTED E_NOTIMPL -#define DPERR_BUSY MAKE_DPHRESULT( 270 ) -#define DPERR_USERCANCEL MAKE_DPHRESULT( 280 ) - - -#define DPOPEN_OPENSESSION 0x00000001 -#define DPOPEN_CREATESESSION 0x00000002 - -#define DPSEND_GUARANTEE 0x00000001 -#define DPSEND_HIGHPRIORITY 0x00000002 -#define DPSEND_TRYONCE 0x00000004 - -#define DPRECEIVE_ALL 0x00000001 -#define DPRECEIVE_TOPLAYER 0x00000002 -#define DPRECEIVE_FROMPLAYER 0x00000004 -#define DPRECEIVE_PEEK 0x00000008 - -#define DPCAPS_NAMESERVICE 0x00000001 // A name server is supported. -#define DPCAPS_NAMESERVER 0x00000002 // You are the name server. -#define DPCAPS_GUARANTEED 0x00000004 // SP's don't have to implement guarantees. - -#define DPENUMSESSIONS_AVAILABLE 0x00000001 // All games that match password (if given) - // and have openings. -#define DPENUMSESSIONS_ALL 0x00000002 -#define DPENUMSESSIONS_PREVIOUS 0x00000004 - -#define DPENUMPLAYERS_ALL 0x00000000 -#define DPENUMPLAYERS_PREVIOUS 0x00000004 -#define DPENUMPLAYERS_LOCAL 0x00000008 -#define DPENUMPLAYERS_REMOTE 0x00000010 -#define DPENUMPLAYERS_GROUP 0x00000020 -#define DPENUMPLAYERS_SESSION 0x00000080 - -// -// This flag is set on the enumsessions callback when the time out has occured. -// This means that there is no session data for this callback. -// If lpdwTimeOut is set to a non-zero value and the EnumSessionsCallback returns -// TRUE then EnumSessions will continue until the next timeout occurs. -// Timeouts are in milliseconds. - -#define DPESC_TIMEDOUT 0x00000001 - - -// -// System message structures and types. -// -// System messages have a leading 4 byte type code to identify the message. -// an app knows it is a system message because it is addressed 'To' player 0. -// - - -#define DPSYS_ADDPLAYER 0x0003 // DPMSG_ADDPLAYER -#define DPSYS_DELETEPLAYER 0x0005 // DPMSG_DELETEPLAYER - -#define DPSYS_ADDPLAYERTOGROUP 0x0007 // DPMSG_GROUPADD - -#define DPSYS_INVITE 0x000e // DPMSG_INVITE, Net only. - -#define DPSYS_DELETEGROUP 0x0020 // DPMSG_DELETEPLAYER -#define DPSYS_DELETEPLAYERFROMGRP 0x0021 // DPMSG_GROUPDELETE -#define DPSYS_SESSIONLOST 0x0031 - -#define DPSYS_CONNECT 0x484b // DPMSG_GENERIC - - - -typedef struct -{ - DWORD dwType; - DWORD dwPlayerType; - DPID dpId; - char szLongName[DPLONGNAMELEN]; - char szShortName[DPSHORTNAMELEN]; - DWORD dwCurrentPlayers; -} DPMSG_ADDPLAYER; - -typedef DPMSG_ADDPLAYER DPMSG_ADDGROUP; - -typedef struct -{ - DWORD dwType; - DPID dpIdGroup; - DPID dpIdPlayer; -} DPMSG_GROUPADD; - -typedef DPMSG_GROUPADD DPMSG_GROUPDELETE; -typedef struct -{ - DWORD dwType; - DPID dpId; -} DPMSG_DELETEPLAYER; - -typedef struct -{ - DWORD dwType; - DPSESSIONDESC dpsDesc; -} DPMSG_INVITE; - - - -typedef struct -{ - DWORD dwType; -} DPMSG_GENERIC; - -#pragma pack(pop) - - -DEFINE_GUID( IID_IDirectPlay, 0x5454e9a0, 0xdb65, 0x11ce, 0x92, 0x1c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72); - - - -#ifdef __cplusplus -}; -#endif - -#endif +/*==========================================================================; + * + * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved. + * + * File: dplay.h + * Content: DirectPlay include file + * + ***************************************************************************/ + +#ifndef __DPLAY_INCLUDED__ +#define __DPLAY_INCLUDED__ +#ifdef _WIN32 +/* for DECLARE_INTERFACE and HRESULT. */ +#include +#endif + +#define _FACDP 0x877 +#define MAKE_DPHRESULT( code ) MAKE_HRESULT( 1, _FACDP, code ) + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push, 1) + + +/*============================================================================ + * + * DirectPlay Structures + * + * Various structures used to invoke DirectPlay. + * + *==========================================================================*/ + +#ifdef __cplusplus +/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ +struct IDirectPlay; +typedef struct IDirectPlay FAR *LPDIRECTPLAY; +#else +typedef struct IDirectPlay FAR *LPDIRECTPLAY; +#endif + +typedef DWORD DPID, FAR *LPDPID; + +typedef struct _DPCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwMaxBufferSize; + DWORD dwMaxQueueSize; // Function of DPlay, not SP. + DWORD dwMaxPlayers; + DWORD dwHundredBaud; // 24 is 2400, 96 is 9600, etc. + DWORD dwLatency; +} DPCAPS; + +typedef DPCAPS FAR *LPDPCAPS; + +#define DPLONGNAMELEN 52 +#define DPSHORTNAMELEN 20 +#define DPSESSIONNAMELEN 32 +#define DPPASSWORDLEN 16 +#define DPUSERRESERVED 16 + +typedef struct +{ + DWORD dwSize; + GUID guidSession; // Id for Game. Null is all games. + DWORD dwSession; // session identifier + DWORD dwMaxPlayers; // Maximum players allowed in game. + DWORD dwCurrentPlayers; // Current players in Game. + DWORD dwFlags; // DPOPEN_* flags + char szSessionName[DPSESSIONNAMELEN];// Human readable name for Game + char szUserField[DPUSERRESERVED]; + DWORD dwReserved1; // Reserved for future MS use. + char szPassword[DPPASSWORDLEN]; // Password to be allowed into game. + DWORD dwReserved2; // Reserved for future MS use. + DWORD dwUser1; + DWORD dwUser2; + DWORD dwUser3; + DWORD dwUser4; +} DPSESSIONDESC; +typedef DPSESSIONDESC FAR *LPDPSESSIONDESC; + + +/* + * Create API + */ +typedef BOOL (FAR PASCAL * LPDPENUMDPCALLBACK)( + LPGUID lpSPGuid, + LPSTR lpFriendlyName, + DWORD dwMajorVersion, + DWORD dwMinorVersion, + LPVOID lpContext); + +typedef BOOL (FAR PASCAL * LPDPENUMSESSIONSCALLBACK)( + LPDPSESSIONDESC lpDPSGameDesc, + LPVOID lpContext, + LPDWORD lpdwTimeOut, + DWORD dwFlags); + + + +extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY FAR *lplpDP, IUnknown FAR *pUnk); +extern HRESULT WINAPI DirectPlayEnumerate( LPDPENUMDPCALLBACK, LPVOID ); + + +/* Player enumeration callback prototype */ +typedef BOOL (FAR PASCAL *LPDPENUMPLAYERSCALLBACK)( + DPID dpId, + LPSTR lpFriendlyName, + LPSTR lpFormalName, + DWORD dwFlags, + LPVOID lpContext ); + +/* + * IDirectPlay + */ +#undef INTERFACE +#define INTERFACE IDirectPlay +#ifdef _WIN32 +DECLARE_INTERFACE_( IDirectPlay, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectPlay methods ***/ + STDMETHOD(AddPlayerToGroup) (THIS_ DPID, DPID) PURE; + STDMETHOD(Close) (THIS) PURE; + STDMETHOD(CreatePlayer) (THIS_ LPDPID,LPSTR,LPSTR,LPHANDLE) PURE; + STDMETHOD(CreateGroup) (THIS_ LPDPID,LPSTR,LPSTR) PURE; + STDMETHOD(DeletePlayerFromGroup)(THIS_ DPID,DPID) PURE; + STDMETHOD(DestroyPlayer) (THIS_ DPID) PURE; + STDMETHOD(DestroyGroup) (THIS_ DPID) PURE; + STDMETHOD(EnableNewPlayers) (THIS_ BOOL) PURE; + STDMETHOD(EnumGroupPlayers) (THIS_ DPID, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(EnumGroups) (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(EnumPlayers) (THIS_ DWORD, LPDPENUMPLAYERSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(EnumSessions) (THIS_ LPDPSESSIONDESC,DWORD,LPDPENUMSESSIONSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(GetCaps) (THIS_ LPDPCAPS) PURE; + STDMETHOD(GetMessageCount) (THIS_ DPID, LPDWORD) PURE; + STDMETHOD(GetPlayerCaps) (THIS_ DPID, LPDPCAPS) PURE; + STDMETHOD(GetPlayerName) (THIS_ DPID,LPSTR,LPDWORD,LPSTR,LPDWORD) PURE; + STDMETHOD(Initialize) (THIS_ LPGUID) PURE; + STDMETHOD(Open) (THIS_ LPDPSESSIONDESC) PURE; + STDMETHOD(Receive) (THIS_ LPDPID,LPDPID,DWORD,LPVOID,LPDWORD) PURE; + STDMETHOD(SaveSession) (THIS_ LPSTR) PURE; + STDMETHOD(Send) (THIS_ DPID, DPID, DWORD, LPVOID, DWORD) PURE; + STDMETHOD(SetPlayerName) (THIS_ DPID,LPSTR,LPSTR) PURE; +}; +#endif + + + + +/**************************************************************************** + * + * DIRECTPLAY ERRORS + * + * Errors are represented by negative values and cannot be combined. + * + ****************************************************************************/ +#define DP_OK 0 +#define DPERR_ALREADYINITIALIZED MAKE_DPHRESULT( 5 ) +#define DPERR_ACCESSDENIED MAKE_DPHRESULT( 10 ) +#define DPERR_ACTIVEPLAYERS MAKE_DPHRESULT( 20 ) +#define DPERR_BUFFERTOOSMALL MAKE_DPHRESULT( 30 ) +#define DPERR_CANTADDPLAYER MAKE_DPHRESULT( 40 ) +#define DPERR_CANTCREATEGROUP MAKE_DPHRESULT( 50 ) +#define DPERR_CANTCREATEPLAYER MAKE_DPHRESULT( 60 ) +#define DPERR_CANTCREATESESSION MAKE_DPHRESULT( 70 ) +#define DPERR_CAPSNOTAVAILABLEYET MAKE_DPHRESULT( 80 ) +#define DPERR_EXCEPTION MAKE_DPHRESULT( 90 ) +#define DPERR_GENERIC E_FAIL + +#define DPERR_INVALIDFLAGS MAKE_DPHRESULT( 120 ) +#define DPERR_INVALIDOBJECT MAKE_DPHRESULT( 130 ) +#define DPERR_INVALIDPARAM E_INVALIDARG +#define DPERR_INVALIDPARAMS DPERR_INVALIDPARAM +#define DPERR_INVALIDPLAYER MAKE_DPHRESULT( 150 ) +#define DPERR_NOCAPS MAKE_DPHRESULT( 160 ) +#define DPERR_NOCONNECTION MAKE_DPHRESULT( 170 ) +#define DPERR_NOMEMORY E_OUTOFMEMORY +#define DPERR_OUTOFMEMORY DPERR_NOMEMORY +#define DPERR_NOMESSAGES MAKE_DPHRESULT( 190 ) +#define DPERR_NONAMESERVERFOUND MAKE_DPHRESULT( 200 ) +#define DPERR_NOPLAYERS MAKE_DPHRESULT( 210 ) +#define DPERR_NOSESSIONS MAKE_DPHRESULT( 220 ) +#define DPERR_SENDTOOBIG MAKE_DPHRESULT( 230 ) +#define DPERR_TIMEOUT MAKE_DPHRESULT( 240 ) +#define DPERR_UNAVAILABLE MAKE_DPHRESULT( 250 ) +#define DPERR_UNSUPPORTED E_NOTIMPL +#define DPERR_BUSY MAKE_DPHRESULT( 270 ) +#define DPERR_USERCANCEL MAKE_DPHRESULT( 280 ) + + +#define DPOPEN_OPENSESSION 0x00000001 +#define DPOPEN_CREATESESSION 0x00000002 + +#define DPSEND_GUARANTEE 0x00000001 +#define DPSEND_HIGHPRIORITY 0x00000002 +#define DPSEND_TRYONCE 0x00000004 + +#define DPRECEIVE_ALL 0x00000001 +#define DPRECEIVE_TOPLAYER 0x00000002 +#define DPRECEIVE_FROMPLAYER 0x00000004 +#define DPRECEIVE_PEEK 0x00000008 + +#define DPCAPS_NAMESERVICE 0x00000001 // A name server is supported. +#define DPCAPS_NAMESERVER 0x00000002 // You are the name server. +#define DPCAPS_GUARANTEED 0x00000004 // SP's don't have to implement guarantees. + +#define DPENUMSESSIONS_AVAILABLE 0x00000001 // All games that match password (if given) + // and have openings. +#define DPENUMSESSIONS_ALL 0x00000002 +#define DPENUMSESSIONS_PREVIOUS 0x00000004 + +#define DPENUMPLAYERS_ALL 0x00000000 +#define DPENUMPLAYERS_PREVIOUS 0x00000004 +#define DPENUMPLAYERS_LOCAL 0x00000008 +#define DPENUMPLAYERS_REMOTE 0x00000010 +#define DPENUMPLAYERS_GROUP 0x00000020 +#define DPENUMPLAYERS_SESSION 0x00000080 + +// +// This flag is set on the enumsessions callback when the time out has occured. +// This means that there is no session data for this callback. +// If lpdwTimeOut is set to a non-zero value and the EnumSessionsCallback returns +// TRUE then EnumSessions will continue until the next timeout occurs. +// Timeouts are in milliseconds. + +#define DPESC_TIMEDOUT 0x00000001 + + +// +// System message structures and types. +// +// System messages have a leading 4 byte type code to identify the message. +// an app knows it is a system message because it is addressed 'To' player 0. +// + + +#define DPSYS_ADDPLAYER 0x0003 // DPMSG_ADDPLAYER +#define DPSYS_DELETEPLAYER 0x0005 // DPMSG_DELETEPLAYER + +#define DPSYS_ADDPLAYERTOGROUP 0x0007 // DPMSG_GROUPADD + +#define DPSYS_INVITE 0x000e // DPMSG_INVITE, Net only. + +#define DPSYS_DELETEGROUP 0x0020 // DPMSG_DELETEPLAYER +#define DPSYS_DELETEPLAYERFROMGRP 0x0021 // DPMSG_GROUPDELETE +#define DPSYS_SESSIONLOST 0x0031 + +#define DPSYS_CONNECT 0x484b // DPMSG_GENERIC + + + +typedef struct +{ + DWORD dwType; + DWORD dwPlayerType; + DPID dpId; + char szLongName[DPLONGNAMELEN]; + char szShortName[DPSHORTNAMELEN]; + DWORD dwCurrentPlayers; +} DPMSG_ADDPLAYER; + +typedef DPMSG_ADDPLAYER DPMSG_ADDGROUP; + +typedef struct +{ + DWORD dwType; + DPID dpIdGroup; + DPID dpIdPlayer; +} DPMSG_GROUPADD; + +typedef DPMSG_GROUPADD DPMSG_GROUPDELETE; +typedef struct +{ + DWORD dwType; + DPID dpId; +} DPMSG_DELETEPLAYER; + +typedef struct +{ + DWORD dwType; + DPSESSIONDESC dpsDesc; +} DPMSG_INVITE; + + + +typedef struct +{ + DWORD dwType; +} DPMSG_GENERIC; + +#pragma pack(pop) + + +DEFINE_GUID( IID_IDirectPlay, 0x5454e9a0, 0xdb65, 0x11ce, 0x92, 0x1c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72); + + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/WinQuake/dxsdk/SDK/INC/DSETUP.H b/WinQuake/dxsdk/SDK/INC/DSETUP.H index b9075ef..5004105 100644 --- a/WinQuake/dxsdk/SDK/INC/DSETUP.H +++ b/WinQuake/dxsdk/SDK/INC/DSETUP.H @@ -1,66 +1,66 @@ -/*========================================================================== - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: dsetup.h - * Content: DirectXSetup, error codes and flags - ***************************************************************************/ - -#ifndef __DSETUP_H__ -#define __DSETUP_H__ - -#ifdef _WIN32 -#define COM_NO_WINDOWS_H -#include -#else -#define GUID void -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define DSETUPERR_BADWINDOWSVERSION -1 -#define DSETUPERR_SOURCEFILENOTFOUND -2 -#define DSETUPERR_BADSOURCESIZE -3 -#define DSETUPERR_BADSOURCETIME -4 -#define DSETUPERR_NOCOPY -5 -#define DSETUPERR_OUTOFDISKSPACE -6 -#define DSETUPERR_CANTFINDINF -7 -#define DSETUPERR_CANTFINDDIR -8 -#define DSETUPERR_INTERNAL -9 -#define DSETUPERR_NTWITHNO3D -10 - - -#define MAX_INFLINE (16*1024) -#define MAX_DESCRIPTION 256 - -#define DSETUP_DDRAW 0x00000001 /* install DirectDraw */ -#define DSETUP_DSOUND 0x00000002 /* install DirectSound */ -#define DSETUP_DPLAY 0x00000004 /* install DirectPlay */ -#define DSETUP_DDRAWDRV 0x00000008 /* install DirectDraw Drivers */ -#define DSETUP_DSOUNDDRV 0x00000010 /* install DirectSound Drivers */ -#define DSETUP_DPLAYSP 0x00000020 /* install DirectPlay Providers */ -#define DSETUP_DVIDEO 0x00000040 /* install DirectVideo */ -#define DSETUP_REINSTALL 0x00000080 /* install DirectX even if existing components have the same version */ -#define DSETUP_DRVINFONLY 0x00000100 /* install DirectX inf files but not drivers */ -#define DSETUP_D3D 0x00000200 /* install Direct3D */ -#define DSETUP_REQUIRESD3D 0x00000400 | DSETUP_D3D /* install Direct3D, pop up dialog box on NT, if no D3D present */ - -#define DSETUP_DIRECTX (DSETUP_D3D | DSETUP_DDRAW | DSETUP_DSOUND | DSETUP_DPLAY | DSETUP_DDRAWDRV | DSETUP_DSOUNDDRV | DSETUP_DPLAYSP) - -int WINAPI DirectXSetup( HWND hwnd, LPSTR root_path, DWORD flags ); -int WINAPI DirectXDeviceDriverSetup( HWND hwnd, LPSTR driver_class, LPSTR inf_path, LPSTR driver_path, DWORD flags ); -int WINAPI DirectXSetupIsJapan( void ); -int WINAPI DirectXSetupIsJapanNec( void ); - -typedef int (WINAPI * LPDIRECTXSETUP)( HWND, LPSTR, DWORD ); -typedef int (WINAPI * LPDIRECTXDEVICEDRIVERSETUP)( HWND, LPSTR, LPSTR, LPSTR, DWORD ); -typedef int (WINAPI * LPDIRECTXSETUPISJAPAN)( void ); -typedef int (WINAPI * LPDIRECTXSETUPISJAPANNEC)( void ); - -#ifdef __cplusplus -}; -#endif - -#endif +/*========================================================================== + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: dsetup.h + * Content: DirectXSetup, error codes and flags + ***************************************************************************/ + +#ifndef __DSETUP_H__ +#define __DSETUP_H__ + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#else +#define GUID void +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define DSETUPERR_BADWINDOWSVERSION -1 +#define DSETUPERR_SOURCEFILENOTFOUND -2 +#define DSETUPERR_BADSOURCESIZE -3 +#define DSETUPERR_BADSOURCETIME -4 +#define DSETUPERR_NOCOPY -5 +#define DSETUPERR_OUTOFDISKSPACE -6 +#define DSETUPERR_CANTFINDINF -7 +#define DSETUPERR_CANTFINDDIR -8 +#define DSETUPERR_INTERNAL -9 +#define DSETUPERR_NTWITHNO3D -10 + + +#define MAX_INFLINE (16*1024) +#define MAX_DESCRIPTION 256 + +#define DSETUP_DDRAW 0x00000001 /* install DirectDraw */ +#define DSETUP_DSOUND 0x00000002 /* install DirectSound */ +#define DSETUP_DPLAY 0x00000004 /* install DirectPlay */ +#define DSETUP_DDRAWDRV 0x00000008 /* install DirectDraw Drivers */ +#define DSETUP_DSOUNDDRV 0x00000010 /* install DirectSound Drivers */ +#define DSETUP_DPLAYSP 0x00000020 /* install DirectPlay Providers */ +#define DSETUP_DVIDEO 0x00000040 /* install DirectVideo */ +#define DSETUP_REINSTALL 0x00000080 /* install DirectX even if existing components have the same version */ +#define DSETUP_DRVINFONLY 0x00000100 /* install DirectX inf files but not drivers */ +#define DSETUP_D3D 0x00000200 /* install Direct3D */ +#define DSETUP_REQUIRESD3D 0x00000400 | DSETUP_D3D /* install Direct3D, pop up dialog box on NT, if no D3D present */ + +#define DSETUP_DIRECTX (DSETUP_D3D | DSETUP_DDRAW | DSETUP_DSOUND | DSETUP_DPLAY | DSETUP_DDRAWDRV | DSETUP_DSOUNDDRV | DSETUP_DPLAYSP) + +int WINAPI DirectXSetup( HWND hwnd, LPSTR root_path, DWORD flags ); +int WINAPI DirectXDeviceDriverSetup( HWND hwnd, LPSTR driver_class, LPSTR inf_path, LPSTR driver_path, DWORD flags ); +int WINAPI DirectXSetupIsJapan( void ); +int WINAPI DirectXSetupIsJapanNec( void ); + +typedef int (WINAPI * LPDIRECTXSETUP)( HWND, LPSTR, DWORD ); +typedef int (WINAPI * LPDIRECTXDEVICEDRIVERSETUP)( HWND, LPSTR, LPSTR, LPSTR, DWORD ); +typedef int (WINAPI * LPDIRECTXSETUPISJAPAN)( void ); +typedef int (WINAPI * LPDIRECTXSETUPISJAPANNEC)( void ); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/WinQuake/dxsdk/SDK/INC/DSOUND.H b/WinQuake/dxsdk/SDK/INC/DSOUND.H index 3cf65fb..11a243e 100644 --- a/WinQuake/dxsdk/SDK/INC/DSOUND.H +++ b/WinQuake/dxsdk/SDK/INC/DSOUND.H @@ -1,366 +1,366 @@ -/*==========================================================================; - * - * Copyright (C) 1995,1996 Microsoft Corporation. All Rights Reserved. - * - * File: dsound.h - * Content: DirectSound include file - * - ***************************************************************************/ - -#ifndef __DSOUND_INCLUDED__ -#define __DSOUND_INCLUDED__ - -#ifdef _WIN32 -#define COM_NO_WINDOWS_H -#include -#endif - -#define _FACDS 0x878 -#define MAKE_DSHRESULT( code ) MAKE_HRESULT( 1, _FACDS, code ) - -#ifdef __cplusplus -extern "C" { -#endif - -// Direct Sound Component GUID {47D4D946-62E8-11cf-93BC-444553540000} -DEFINE_GUID(CLSID_DirectSound, -0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); - -// DirectSound 279afa83-4981-11ce-a521-0020af0be560 -DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); -// DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560 -DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); - - - -//==========================================================================; -// -// Structures... -// -//==========================================================================; -#ifdef __cplusplus -/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ -struct IDirectSound; -struct IDirectSoundBuffer; -#endif - -typedef struct IDirectSound *LPDIRECTSOUND; -typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; -typedef struct IDirectSoundBuffer **LPLPDIRECTSOUNDBUFFER; - - -typedef struct _DSCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwMinSecondarySampleRate; - DWORD dwMaxSecondarySampleRate; - DWORD dwPrimaryBuffers; - DWORD dwMaxHwMixingAllBuffers; - DWORD dwMaxHwMixingStaticBuffers; - DWORD dwMaxHwMixingStreamingBuffers; - DWORD dwFreeHwMixingAllBuffers; - DWORD dwFreeHwMixingStaticBuffers; - DWORD dwFreeHwMixingStreamingBuffers; - DWORD dwMaxHw3DAllBuffers; - DWORD dwMaxHw3DStaticBuffers; - DWORD dwMaxHw3DStreamingBuffers; - DWORD dwFreeHw3DAllBuffers; - DWORD dwFreeHw3DStaticBuffers; - DWORD dwFreeHw3DStreamingBuffers; - DWORD dwTotalHwMemBytes; - DWORD dwFreeHwMemBytes; - DWORD dwMaxContigFreeHwMemBytes; - DWORD dwUnlockTransferRateHwBuffers; - DWORD dwPlayCpuOverheadSwBuffers; - DWORD dwReserved1; - DWORD dwReserved2; -} DSCAPS, *LPDSCAPS; - -typedef struct _DSBCAPS -{ - - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwUnlockTransferRate; - DWORD dwPlayCpuOverhead; -} DSBCAPS, *LPDSBCAPS; - -typedef struct _DSBUFFERDESC -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -} DSBUFFERDESC, *LPDSBUFFERDESC; - - - -typedef LPVOID* LPLPVOID; - - -typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID); -typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID); - -extern HRESULT WINAPI DirectSoundCreate(GUID FAR * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter ); -extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpCallback, LPVOID lpContext ); -extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext ); - -#ifdef UNICODE -#define LPDSENUMCALLBACK LPDSENUMCALLBACKW -#define DirectSoundEnumerate DirectSoundEnumerateW -#else -#define LPDSENUMCALLBACK LPDSENUMCALLBACKA -#define DirectSoundEnumerate DirectSoundEnumerateA -#endif - -// -// IDirectSound -// -#undef INTERFACE -#define INTERFACE IDirectSound -#ifdef _WIN32 -DECLARE_INTERFACE_( IDirectSound, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectSound methods ***/ - - STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE; - STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE; - STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE; - STDMETHOD( SetCooperativeLevel)(THIS_ HWND, DWORD ) PURE; - STDMETHOD( Compact)(THIS ) PURE; - STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE; - STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE; - STDMETHOD( Initialize)(THIS_ GUID FAR * ) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSound_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSound_Release(p) (p)->lpVtbl->Release(p) -#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) -#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) -#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) -#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) -#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#endif - -#endif - -// -// IDirectSoundBuffer -// -#undef INTERFACE -#define INTERFACE IDirectSoundBuffer -#ifdef _WIN32 -DECLARE_INTERFACE_( IDirectSoundBuffer, IUnknown ) -{ - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - /*** IDirectSoundBuffer methods ***/ - - STDMETHOD( GetCaps)(THIS_ LPDSBCAPS ) PURE; - STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE; - STDMETHOD( GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE; - STDMETHOD( GetVolume)(THIS_ LPLONG ) PURE; - STDMETHOD( GetPan)(THIS_ LPLONG ) PURE; - STDMETHOD( GetFrequency)(THIS_ LPDWORD ) PURE; - STDMETHOD( GetStatus)(THIS_ LPDWORD ) PURE; - STDMETHOD( Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE; - STDMETHOD( Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE; - STDMETHOD( Play)(THIS_ DWORD,DWORD,DWORD ) PURE; - STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE; - STDMETHOD( SetFormat)(THIS_ LPWAVEFORMATEX ) PURE; - STDMETHOD( SetVolume)(THIS_ LONG ) PURE; - STDMETHOD( SetPan)(THIS_ LONG ) PURE; - STDMETHOD( SetFrequency)(THIS_ DWORD ) PURE; - STDMETHOD( Stop)(THIS ) PURE; - STDMETHOD( Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE; - STDMETHOD( Restore)(THIS ) PURE; -}; - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundBuffer_Release(p) (p)->lpVtbl->Release(p) -#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) -#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) -#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) -#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) -#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) -#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) -#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) -#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) -#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) -#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) -#endif - -#endif - - - -/* - * Return Codes - */ - -#define DS_OK 0 - -/* - * The call failed because resources (such as a priority level) - * were already being used by another caller. - */ -#define DSERR_ALLOCATED MAKE_DSHRESULT( 10 ) -/* - * The control (vol,pan,etc.) requested by the caller is not available. - */ -#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT( 30 ) -/* - * An invalid parameter was passed to the returning function - */ -#define DSERR_INVALIDPARAM E_INVALIDARG -/* - * This call is not valid for the current state of this object - */ -#define DSERR_INVALIDCALL MAKE_DSHRESULT( 50 ) -/* - * An undetermined error occured inside the DSound subsystem - */ -#define DSERR_GENERIC E_FAIL -/* - * The caller does not have the priority level required for the function to - * succeed. - */ -#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT( 70 ) -/* - * The DSound subsystem couldn't allocate sufficient memory to complete the - * caller's request. - */ -#define DSERR_OUTOFMEMORY E_OUTOFMEMORY -/* - * The specified WAVE format is not supported - */ -#define DSERR_BADFORMAT MAKE_DSHRESULT( 100 ) -/* - * The function called is not supported at this time - */ -#define DSERR_UNSUPPORTED E_NOTIMPL -/* - * No sound driver is available for use - */ -#define DSERR_NODRIVER MAKE_DSHRESULT( 120 ) -/* - * This object is already initialized - */ -#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT( 130 ) -/* - * This object does not support aggregation - */ -#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION -/* - * The buffer memory has been lost, and must be Restored. - */ -#define DSERR_BUFFERLOST MAKE_DSHRESULT( 150 ) -/* - * Another app has a higher priority level, preventing this call from - * succeeding. - */ -#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT( 160 ) -/* - * The Initialize() member on the Direct Sound Object has not been - * called or called successfully before calls to other members. - */ -#define DSERR_UNINITIALIZED MAKE_DSHRESULT( 170 ) - - - - -//==========================================================================; -// -// Flags... -// -//==========================================================================; - -#define DSCAPS_PRIMARYMONO 0x00000001 -#define DSCAPS_PRIMARYSTEREO 0x00000002 -#define DSCAPS_PRIMARY8BIT 0x00000004 -#define DSCAPS_PRIMARY16BIT 0x00000008 -#define DSCAPS_CONTINUOUSRATE 0x00000010 -#define DSCAPS_EMULDRIVER 0x00000020 -#define DSCAPS_CERTIFIED 0x00000040 -#define DSCAPS_SECONDARYMONO 0x00000100 -#define DSCAPS_SECONDARYSTEREO 0x00000200 -#define DSCAPS_SECONDARY8BIT 0x00000400 -#define DSCAPS_SECONDARY16BIT 0x00000800 - - - -#define DSBPLAY_LOOPING 0x00000001 - - - -#define DSBSTATUS_PLAYING 0x00000001 -#define DSBSTATUS_BUFFERLOST 0x00000002 -#define DSBSTATUS_LOOPING 0x00000004 - - -#define DSBLOCK_FROMWRITECURSOR 0x00000001 - - - -#define DSSCL_NORMAL 1 -#define DSSCL_PRIORITY 2 -#define DSSCL_EXCLUSIVE 3 -#define DSSCL_WRITEPRIMARY 4 - - - -#define DSBCAPS_PRIMARYBUFFER 0x00000001 -#define DSBCAPS_STATIC 0x00000002 -#define DSBCAPS_LOCHARDWARE 0x00000004 -#define DSBCAPS_LOCSOFTWARE 0x00000008 -#define DSBCAPS_CTRLFREQUENCY 0x00000020 -#define DSBCAPS_CTRLPAN 0x00000040 -#define DSBCAPS_CTRLVOLUME 0x00000080 -#define DSBCAPS_CTRLDEFAULT 0x000000E0 // Pan + volume + frequency. -#define DSBCAPS_CTRLALL 0x000000E0 // All control capabilities -#define DSBCAPS_STICKYFOCUS 0x00004000 -#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 // More accurate play cursor under emulation - - - - -#define DSSPEAKER_HEADPHONE 1 -#define DSSPEAKER_MONO 2 -#define DSSPEAKER_QUAD 3 -#define DSSPEAKER_STEREO 4 -#define DSSPEAKER_SURROUND 5 - - - - - - -#ifdef __cplusplus -}; -#endif - -#endif /* __DSOUND_INCLUDED__ */ +/*==========================================================================; + * + * Copyright (C) 1995,1996 Microsoft Corporation. All Rights Reserved. + * + * File: dsound.h + * Content: DirectSound include file + * + ***************************************************************************/ + +#ifndef __DSOUND_INCLUDED__ +#define __DSOUND_INCLUDED__ + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#endif + +#define _FACDS 0x878 +#define MAKE_DSHRESULT( code ) MAKE_HRESULT( 1, _FACDS, code ) + +#ifdef __cplusplus +extern "C" { +#endif + +// Direct Sound Component GUID {47D4D946-62E8-11cf-93BC-444553540000} +DEFINE_GUID(CLSID_DirectSound, +0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); + +// DirectSound 279afa83-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); +// DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); + + + +//==========================================================================; +// +// Structures... +// +//==========================================================================; +#ifdef __cplusplus +/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ +struct IDirectSound; +struct IDirectSoundBuffer; +#endif + +typedef struct IDirectSound *LPDIRECTSOUND; +typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; +typedef struct IDirectSoundBuffer **LPLPDIRECTSOUNDBUFFER; + + +typedef struct _DSCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwMinSecondarySampleRate; + DWORD dwMaxSecondarySampleRate; + DWORD dwPrimaryBuffers; + DWORD dwMaxHwMixingAllBuffers; + DWORD dwMaxHwMixingStaticBuffers; + DWORD dwMaxHwMixingStreamingBuffers; + DWORD dwFreeHwMixingAllBuffers; + DWORD dwFreeHwMixingStaticBuffers; + DWORD dwFreeHwMixingStreamingBuffers; + DWORD dwMaxHw3DAllBuffers; + DWORD dwMaxHw3DStaticBuffers; + DWORD dwMaxHw3DStreamingBuffers; + DWORD dwFreeHw3DAllBuffers; + DWORD dwFreeHw3DStaticBuffers; + DWORD dwFreeHw3DStreamingBuffers; + DWORD dwTotalHwMemBytes; + DWORD dwFreeHwMemBytes; + DWORD dwMaxContigFreeHwMemBytes; + DWORD dwUnlockTransferRateHwBuffers; + DWORD dwPlayCpuOverheadSwBuffers; + DWORD dwReserved1; + DWORD dwReserved2; +} DSCAPS, *LPDSCAPS; + +typedef struct _DSBCAPS +{ + + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwUnlockTransferRate; + DWORD dwPlayCpuOverhead; +} DSBCAPS, *LPDSBCAPS; + +typedef struct _DSBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSBUFFERDESC, *LPDSBUFFERDESC; + + + +typedef LPVOID* LPLPVOID; + + +typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID); +typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID); + +extern HRESULT WINAPI DirectSoundCreate(GUID FAR * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter ); +extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpCallback, LPVOID lpContext ); +extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext ); + +#ifdef UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKW +#define DirectSoundEnumerate DirectSoundEnumerateW +#else +#define LPDSENUMCALLBACK LPDSENUMCALLBACKA +#define DirectSoundEnumerate DirectSoundEnumerateA +#endif + +// +// IDirectSound +// +#undef INTERFACE +#define INTERFACE IDirectSound +#ifdef _WIN32 +DECLARE_INTERFACE_( IDirectSound, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectSound methods ***/ + + STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE; + STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE; + STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE; + STDMETHOD( SetCooperativeLevel)(THIS_ HWND, DWORD ) PURE; + STDMETHOD( Compact)(THIS ) PURE; + STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE; + STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE; + STDMETHOD( Initialize)(THIS_ GUID FAR * ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSound_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSound_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) +#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#endif + +#endif + +// +// IDirectSoundBuffer +// +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer +#ifdef _WIN32 +DECLARE_INTERFACE_( IDirectSoundBuffer, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectSoundBuffer methods ***/ + + STDMETHOD( GetCaps)(THIS_ LPDSBCAPS ) PURE; + STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE; + STDMETHOD( GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE; + STDMETHOD( GetVolume)(THIS_ LPLONG ) PURE; + STDMETHOD( GetPan)(THIS_ LPLONG ) PURE; + STDMETHOD( GetFrequency)(THIS_ LPDWORD ) PURE; + STDMETHOD( GetStatus)(THIS_ LPDWORD ) PURE; + STDMETHOD( Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE; + STDMETHOD( Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE; + STDMETHOD( Play)(THIS_ DWORD,DWORD,DWORD ) PURE; + STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE; + STDMETHOD( SetFormat)(THIS_ LPWAVEFORMATEX ) PURE; + STDMETHOD( SetVolume)(THIS_ LONG ) PURE; + STDMETHOD( SetPan)(THIS_ LONG ) PURE; + STDMETHOD( SetFrequency)(THIS_ DWORD ) PURE; + STDMETHOD( Stop)(THIS ) PURE; + STDMETHOD( Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE; + STDMETHOD( Restore)(THIS ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSoundBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSoundBuffer_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) +#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) +#endif + +#endif + + + +/* + * Return Codes + */ + +#define DS_OK 0 + +/* + * The call failed because resources (such as a priority level) + * were already being used by another caller. + */ +#define DSERR_ALLOCATED MAKE_DSHRESULT( 10 ) +/* + * The control (vol,pan,etc.) requested by the caller is not available. + */ +#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT( 30 ) +/* + * An invalid parameter was passed to the returning function + */ +#define DSERR_INVALIDPARAM E_INVALIDARG +/* + * This call is not valid for the current state of this object + */ +#define DSERR_INVALIDCALL MAKE_DSHRESULT( 50 ) +/* + * An undetermined error occured inside the DSound subsystem + */ +#define DSERR_GENERIC E_FAIL +/* + * The caller does not have the priority level required for the function to + * succeed. + */ +#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT( 70 ) +/* + * The DSound subsystem couldn't allocate sufficient memory to complete the + * caller's request. + */ +#define DSERR_OUTOFMEMORY E_OUTOFMEMORY +/* + * The specified WAVE format is not supported + */ +#define DSERR_BADFORMAT MAKE_DSHRESULT( 100 ) +/* + * The function called is not supported at this time + */ +#define DSERR_UNSUPPORTED E_NOTIMPL +/* + * No sound driver is available for use + */ +#define DSERR_NODRIVER MAKE_DSHRESULT( 120 ) +/* + * This object is already initialized + */ +#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT( 130 ) +/* + * This object does not support aggregation + */ +#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION +/* + * The buffer memory has been lost, and must be Restored. + */ +#define DSERR_BUFFERLOST MAKE_DSHRESULT( 150 ) +/* + * Another app has a higher priority level, preventing this call from + * succeeding. + */ +#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT( 160 ) +/* + * The Initialize() member on the Direct Sound Object has not been + * called or called successfully before calls to other members. + */ +#define DSERR_UNINITIALIZED MAKE_DSHRESULT( 170 ) + + + + +//==========================================================================; +// +// Flags... +// +//==========================================================================; + +#define DSCAPS_PRIMARYMONO 0x00000001 +#define DSCAPS_PRIMARYSTEREO 0x00000002 +#define DSCAPS_PRIMARY8BIT 0x00000004 +#define DSCAPS_PRIMARY16BIT 0x00000008 +#define DSCAPS_CONTINUOUSRATE 0x00000010 +#define DSCAPS_EMULDRIVER 0x00000020 +#define DSCAPS_CERTIFIED 0x00000040 +#define DSCAPS_SECONDARYMONO 0x00000100 +#define DSCAPS_SECONDARYSTEREO 0x00000200 +#define DSCAPS_SECONDARY8BIT 0x00000400 +#define DSCAPS_SECONDARY16BIT 0x00000800 + + + +#define DSBPLAY_LOOPING 0x00000001 + + + +#define DSBSTATUS_PLAYING 0x00000001 +#define DSBSTATUS_BUFFERLOST 0x00000002 +#define DSBSTATUS_LOOPING 0x00000004 + + +#define DSBLOCK_FROMWRITECURSOR 0x00000001 + + + +#define DSSCL_NORMAL 1 +#define DSSCL_PRIORITY 2 +#define DSSCL_EXCLUSIVE 3 +#define DSSCL_WRITEPRIMARY 4 + + + +#define DSBCAPS_PRIMARYBUFFER 0x00000001 +#define DSBCAPS_STATIC 0x00000002 +#define DSBCAPS_LOCHARDWARE 0x00000004 +#define DSBCAPS_LOCSOFTWARE 0x00000008 +#define DSBCAPS_CTRLFREQUENCY 0x00000020 +#define DSBCAPS_CTRLPAN 0x00000040 +#define DSBCAPS_CTRLVOLUME 0x00000080 +#define DSBCAPS_CTRLDEFAULT 0x000000E0 // Pan + volume + frequency. +#define DSBCAPS_CTRLALL 0x000000E0 // All control capabilities +#define DSBCAPS_STICKYFOCUS 0x00004000 +#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 // More accurate play cursor under emulation + + + + +#define DSSPEAKER_HEADPHONE 1 +#define DSSPEAKER_MONO 2 +#define DSSPEAKER_QUAD 3 +#define DSSPEAKER_STEREO 4 +#define DSSPEAKER_SURROUND 5 + + + + + + +#ifdef __cplusplus +}; +#endif + +#endif /* __DSOUND_INCLUDED__ */ diff --git a/WinQuake/dxsdk/SDK/INC/FASTFILE.H b/WinQuake/dxsdk/SDK/INC/FASTFILE.H index 84f49fe..3b470e9 100644 --- a/WinQuake/dxsdk/SDK/INC/FASTFILE.H +++ b/WinQuake/dxsdk/SDK/INC/FASTFILE.H @@ -1,24 +1,24 @@ -/*========================================================================== - * - * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. - * - * File: fastfile.h - * Content: Definitions for fastfile access. - * - * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, - * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED - * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. - * - ***************************************************************************/ - -typedef LPVOID HFASTFILE; - -extern BOOL FastFileInit( LPSTR fname, int max_handles ); -extern void FastFileFini( void ); -extern HFASTFILE FastFileOpen( LPSTR name ); -extern BOOL FastFileClose( HFASTFILE pfe ); -extern BOOL FastFileRead( HFASTFILE pfh, LPVOID ptr, int size ); -extern BOOL FastFileSeek( HFASTFILE pfe, int off, int how ); -extern long FastFileTell( HFASTFILE pfe ); -extern LPVOID FastFileLock( HFASTFILE pfe, int off, int len ); -extern BOOL FastFileUnlock( HFASTFILE pfe, int off, int len ); +/*========================================================================== + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: fastfile.h + * Content: Definitions for fastfile access. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + * + ***************************************************************************/ + +typedef LPVOID HFASTFILE; + +extern BOOL FastFileInit( LPSTR fname, int max_handles ); +extern void FastFileFini( void ); +extern HFASTFILE FastFileOpen( LPSTR name ); +extern BOOL FastFileClose( HFASTFILE pfe ); +extern BOOL FastFileRead( HFASTFILE pfh, LPVOID ptr, int size ); +extern BOOL FastFileSeek( HFASTFILE pfe, int off, int how ); +extern long FastFileTell( HFASTFILE pfe ); +extern LPVOID FastFileLock( HFASTFILE pfe, int off, int len ); +extern BOOL FastFileUnlock( HFASTFILE pfe, int off, int len ); diff --git a/WinQuake/gas2masm/gas2masm.c b/WinQuake/gas2masm/gas2masm.c index 2e1eb87..f477931 100644 --- a/WinQuake/gas2masm/gas2masm.c +++ b/WinQuake/gas2masm/gas2masm.c @@ -1,1056 +1,1056 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// gas to MASM source code converter -// - -#include -#include -#include - -#define MAX_TOKENS 100 -#define MAX_TOKEN_LENGTH 1024 -#define LF 0x0A - -typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat; -typedef enum {NOSEG, DATASEG, TEXTSEG} segtype; - -int tokennum; -int inline, outline; - -char *token; -char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1]; - -segtype currentseg = NOSEG; - -typedef struct { - char *text; - char *emit; - int numtokens; - void (*parsefunc) (void); -} parsefield; - - -void errorexit (void); - - -//============================================== - -typedef struct { - char *text; - char *emit; - int len; -} regdesc; - -regdesc reglist[] = { - {"%eax", "eax", 4}, - {"%ebx", "ebx", 4}, - {"%ecx", "ecx", 4}, - {"%edx", "edx", 4}, - {"%esi", "esi", 4}, - {"%edi", "edi", 4}, - {"%ebp", "ebp", 4}, - {"%esp", "esp", 4}, - {"%ax", "ax", 3}, - {"%bx", "bx", 3}, - {"%cx", "cx", 3}, - {"%dx", "dx", 3}, - {"%si", "si", 3}, - {"%di", "di", 3}, - {"%bp", "bp", 3}, - {"%sp", "sp", 3}, - {"%al", "al", 3}, - {"%bl", "bl", 3}, - {"%cl", "cl", 3}, - {"%dl", "dl", 3}, - {"%ah", "ah", 3}, - {"%bh", "bh", 3}, - {"%ch", "ch", 3}, - {"%dh", "dh", 3}, - {"%st(0)", "st(0)", 6}, - {"%st(1)", "st(1)", 6}, - {"%st(2)", "st(2)", 6}, - {"%st(3)", "st(3)", 6}, - {"%st(4)", "st(4)", 6}, - {"%st(5)", "st(5)", 6}, - {"%st(6)", "st(6)", 6}, - {"%st(7)", "st(7)", 6}, -}; - -int numregs = sizeof (reglist) / sizeof (reglist[0]); - -//============================================== - - -void emitanoperand (int tnum, char *type, int notdata) -{ - int i, index, something_outside_parens, regfound; - int parencount; - char *pt; - char temp[MAX_TOKEN_LENGTH+1]; - - pt = tokens[tnum]; - - if (pt[0] == '%') - { - // register - for (i=0 ; i '9') || (pt[2] < '0')) - { - i = 2; - printf ("offset "); - - parencount = 1; - - while ((pt[i] != ')') || (parencount > 1)) - { - if (!pt[i]) - { - fprintf (stderr, "mismatched parens"); - errorexit (); - } - - if (pt[i] == ')') - parencount--; - else if (pt[i] == '(') - parencount++; - - printf ("%c", pt[i]); - i++; - } - } - else - { - pt++; - - parencount = 1; - - for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++) - { - if (!pt[i]) - { - fprintf (stderr, "mismatched parens"); - errorexit (); - } - - if (pt[i] == ')') - parencount--; - else if (pt[i] == '(') - parencount++; - } - - pt[i] = 0; - - if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) - { - printf ("0%sh", &pt[3]); - } - else - { - printf ("%s", &pt[1]); - } - } - } - else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) - { - printf ("0%sh", &pt[3]); - } - else if ((pt[1] >= '0') && (pt[1] <= '9')) - { - printf ("%s", &pt[1]); - } - else - { - printf ("offset %s", &pt[1]); - } - } - else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9'))) - { - pt--; - - if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) - { - printf ("0%sh", &pt[3]); - } - else - { - printf ("%s", &pt[1]); - } - } - else - { - // must be a memory location - strcpy (temp, type); - index = strlen (temp); - - if (notdata) - temp[index++] = '['; - - something_outside_parens = 0; - - while (*pt) - { - if (index > (MAX_TOKEN_LENGTH - 10)) - { - fprintf (stderr, "Error: operand too long %s\n", - tokens[tnum]); - errorexit (); - } - - if (*pt != ')') - { - if (*pt == '(') - { - if (something_outside_parens) - temp[index++] = '+'; - } - else if (*pt == '%') - { - regfound = 0; - - for (i=0 ; i= '1') && (*pt <= '8')) - { - temp[index++] = '*'; - temp[index++] = *pt; - } - else if (*pt != ')') - { - if (temp[index-1] != '+') - temp[index++] = '+'; - } - } - else - { - something_outside_parens = 1; - - // handle hexadecimal constants in addresses - if ((*pt == '0') && - ((*(pt+1) == 'x') || (*(pt+1) == 'X'))) - { - pt += 2; - - do - { - temp[index++] = *pt++; - } while (((*pt >= '0') && (*pt <= '9')) || - ((*pt >= 'a') && (*pt <= 'f')) || - ((*pt >= 'A') && (*pt <= 'F'))); - - pt--; - temp[index++] = 'h'; - } - else - { - temp[index++] = *pt; - } - } - } - - pt++; - } - - if (notdata) - temp[index++] = ']'; - - temp[index] = 0; - printf ("%s", temp); - } -} - - -void datasegstart (void) -{ - if (currentseg == DATASEG) - return; - - if (currentseg == TEXTSEG) - printf ("_TEXT ENDS\n"); - - printf ("_DATA SEGMENT"); - - currentseg = DATASEG; -} - - -void textsegstart (void) -{ - if (currentseg == TEXTSEG) - return; - - if (currentseg == DATASEG) - printf ("_DATA ENDS\n"); - - printf ("_TEXT SEGMENT"); - - currentseg = TEXTSEG; -} - - -void emitdata (void) -{ - int i; - - for (i=1 ; i<(tokennum-1) ; i++) - printf (" %s,", tokens[i]); - - printf (" %s", tokens[tokennum-1]); -} - - -void emitonedata (void) -{ - - printf (" %s", tokens[1]); -} - - -void emitonecalldata (void) -{ - int i, isaddr, len; - - if (tokens[1][0] == '*') - { - printf (" dword ptr[%s]", &tokens[1][1]); - } - else - { - isaddr = 0; - len = strlen(tokens[1]); - - for (i=0 ; i 127) || - (c == ',')) - { - return WHITESPACE; - } - - return NOT_WHITESPACE; -} - - -int gettoken (void) -{ - char c; - int count, parencount; - tokenstat stat; - - do - { - if ((c = getchar ()) == EOF) - return FILE_DONE; - - if ((stat = whitespace (c)) == LINE_DONE) - return LINE_DONE; - } while (stat == WHITESPACE); - - token[0] = c; - count = 1; - - if (c == '~') - { - count--; - token[count++] = 'n'; - token[count++] = 'o'; - token[count++] = 't'; - token[count++] = ' '; - } - - if (c == '(') - { - do - { - if ((c = getchar ()) == EOF) - { - fprintf (stderr, "EOF in middle of parentheses\n"); - errorexit (); - } - - token[count++] = c; - - } while (c != ')'); - } - - for ( ;; ) - { - if ((c = getchar ()) == EOF) - { - token[count] = 0; - return TOKEN_AVAILABLE; - } - - if (whitespace (c) == LINE_DONE) - { - if (ungetc (c, stdin) == EOF) - { - fprintf (stderr, "Couldn't unget character\n"); - errorexit (); - } - - token[count] = 0; - return TOKEN_AVAILABLE; - } - - if (whitespace (c) == WHITESPACE) - { - token[count] = 0; - return TOKEN_AVAILABLE; - } - - if (count >= MAX_TOKEN_LENGTH) - { - fprintf (stderr, "Error: token too long\n"); - errorexit (); - } - - token[count++] = c; - - if (c == '~') - { - count--; - token[count++] = 'n'; - token[count++] = 'o'; - token[count++] = 't'; - token[count++] = ' '; - } - else if (c == '(') - { - parencount = 1; - - do - { - if ((c = getchar ()) == EOF) - { - fprintf (stderr, "EOF in middle of parentheses\n"); - errorexit (); - } - - if (c == '(') - parencount++; - else if (c == ')') - parencount--; - - if (c == '~') - { - token[count++] = 'n'; - token[count++] = 'o'; - token[count++] = 't'; - token[count++] = ' '; - } - else - { - token[count++] = c; - } - - } while ((c != ')') || (parencount > 0)); - } - } -} - - -tokenstat parseline (void) -{ - tokenstat stat; - int i, j, firsttoken, labelfound; - int mnemfound; - - firsttoken = 1; - tokennum = 0; - labelfound = 0; - - for ( ;; ) - { - token = tokens[tokennum]; - stat = gettoken (); - - switch (stat) - { - case FILE_DONE: - return FILE_DONE; - - case LINE_DONE: - if (!firsttoken && tokennum) - { - mnemfound = 0; - - for (i=0 ; i 0) && - (parsedata[i].numtokens != tokennum)) || - ((parsedata[i].numtokens < 0) && - (tokennum < -parsedata[i].numtokens))) - { - fprintf (stderr, "mismatched number of tokens\n"); - - for (j=0 ; j= MAX_TOKENS) - { - fprintf (stderr, "Error: too many tokens\n"); - exit (0); - } - - tokennum++; - - break; - - default: - fprintf (stderr, "Error: unknown tokenstat %d\n", stat); - exit (0); - } - } -} - - -void main (int argc, char **argv) -{ - tokenstat stat; - - printf (" .386P\n" - " .model FLAT\n"); - inline = 1; - outline = 3; - - for ( ;; ) - { - stat = parseline (); - inline++; - - switch (stat) - { - case FILE_DONE: - if (currentseg == TEXTSEG) - printf ("_TEXT ENDS\n"); - else if (currentseg == DATASEG) - printf ("_DATA ENDS\n"); - - printf (" END\n"); - exit (0); - - case PARSED_OKAY: - break; - - default: - fprintf (stderr, "Error: unknown tokenstat %d\n", stat); - exit (0); - } - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// gas to MASM source code converter +// + +#include +#include +#include + +#define MAX_TOKENS 100 +#define MAX_TOKEN_LENGTH 1024 +#define LF 0x0A + +typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat; +typedef enum {NOSEG, DATASEG, TEXTSEG} segtype; + +int tokennum; +int inline, outline; + +char *token; +char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1]; + +segtype currentseg = NOSEG; + +typedef struct { + char *text; + char *emit; + int numtokens; + void (*parsefunc) (void); +} parsefield; + + +void errorexit (void); + + +//============================================== + +typedef struct { + char *text; + char *emit; + int len; +} regdesc; + +regdesc reglist[] = { + {"%eax", "eax", 4}, + {"%ebx", "ebx", 4}, + {"%ecx", "ecx", 4}, + {"%edx", "edx", 4}, + {"%esi", "esi", 4}, + {"%edi", "edi", 4}, + {"%ebp", "ebp", 4}, + {"%esp", "esp", 4}, + {"%ax", "ax", 3}, + {"%bx", "bx", 3}, + {"%cx", "cx", 3}, + {"%dx", "dx", 3}, + {"%si", "si", 3}, + {"%di", "di", 3}, + {"%bp", "bp", 3}, + {"%sp", "sp", 3}, + {"%al", "al", 3}, + {"%bl", "bl", 3}, + {"%cl", "cl", 3}, + {"%dl", "dl", 3}, + {"%ah", "ah", 3}, + {"%bh", "bh", 3}, + {"%ch", "ch", 3}, + {"%dh", "dh", 3}, + {"%st(0)", "st(0)", 6}, + {"%st(1)", "st(1)", 6}, + {"%st(2)", "st(2)", 6}, + {"%st(3)", "st(3)", 6}, + {"%st(4)", "st(4)", 6}, + {"%st(5)", "st(5)", 6}, + {"%st(6)", "st(6)", 6}, + {"%st(7)", "st(7)", 6}, +}; + +int numregs = sizeof (reglist) / sizeof (reglist[0]); + +//============================================== + + +void emitanoperand (int tnum, char *type, int notdata) +{ + int i, index, something_outside_parens, regfound; + int parencount; + char *pt; + char temp[MAX_TOKEN_LENGTH+1]; + + pt = tokens[tnum]; + + if (pt[0] == '%') + { + // register + for (i=0 ; i '9') || (pt[2] < '0')) + { + i = 2; + printf ("offset "); + + parencount = 1; + + while ((pt[i] != ')') || (parencount > 1)) + { + if (!pt[i]) + { + fprintf (stderr, "mismatched parens"); + errorexit (); + } + + if (pt[i] == ')') + parencount--; + else if (pt[i] == '(') + parencount++; + + printf ("%c", pt[i]); + i++; + } + } + else + { + pt++; + + parencount = 1; + + for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++) + { + if (!pt[i]) + { + fprintf (stderr, "mismatched parens"); + errorexit (); + } + + if (pt[i] == ')') + parencount--; + else if (pt[i] == '(') + parencount++; + } + + pt[i] = 0; + + if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) + { + printf ("0%sh", &pt[3]); + } + else + { + printf ("%s", &pt[1]); + } + } + } + else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) + { + printf ("0%sh", &pt[3]); + } + else if ((pt[1] >= '0') && (pt[1] <= '9')) + { + printf ("%s", &pt[1]); + } + else + { + printf ("offset %s", &pt[1]); + } + } + else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9'))) + { + pt--; + + if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) + { + printf ("0%sh", &pt[3]); + } + else + { + printf ("%s", &pt[1]); + } + } + else + { + // must be a memory location + strcpy (temp, type); + index = strlen (temp); + + if (notdata) + temp[index++] = '['; + + something_outside_parens = 0; + + while (*pt) + { + if (index > (MAX_TOKEN_LENGTH - 10)) + { + fprintf (stderr, "Error: operand too long %s\n", + tokens[tnum]); + errorexit (); + } + + if (*pt != ')') + { + if (*pt == '(') + { + if (something_outside_parens) + temp[index++] = '+'; + } + else if (*pt == '%') + { + regfound = 0; + + for (i=0 ; i= '1') && (*pt <= '8')) + { + temp[index++] = '*'; + temp[index++] = *pt; + } + else if (*pt != ')') + { + if (temp[index-1] != '+') + temp[index++] = '+'; + } + } + else + { + something_outside_parens = 1; + + // handle hexadecimal constants in addresses + if ((*pt == '0') && + ((*(pt+1) == 'x') || (*(pt+1) == 'X'))) + { + pt += 2; + + do + { + temp[index++] = *pt++; + } while (((*pt >= '0') && (*pt <= '9')) || + ((*pt >= 'a') && (*pt <= 'f')) || + ((*pt >= 'A') && (*pt <= 'F'))); + + pt--; + temp[index++] = 'h'; + } + else + { + temp[index++] = *pt; + } + } + } + + pt++; + } + + if (notdata) + temp[index++] = ']'; + + temp[index] = 0; + printf ("%s", temp); + } +} + + +void datasegstart (void) +{ + if (currentseg == DATASEG) + return; + + if (currentseg == TEXTSEG) + printf ("_TEXT ENDS\n"); + + printf ("_DATA SEGMENT"); + + currentseg = DATASEG; +} + + +void textsegstart (void) +{ + if (currentseg == TEXTSEG) + return; + + if (currentseg == DATASEG) + printf ("_DATA ENDS\n"); + + printf ("_TEXT SEGMENT"); + + currentseg = TEXTSEG; +} + + +void emitdata (void) +{ + int i; + + for (i=1 ; i<(tokennum-1) ; i++) + printf (" %s,", tokens[i]); + + printf (" %s", tokens[tokennum-1]); +} + + +void emitonedata (void) +{ + + printf (" %s", tokens[1]); +} + + +void emitonecalldata (void) +{ + int i, isaddr, len; + + if (tokens[1][0] == '*') + { + printf (" dword ptr[%s]", &tokens[1][1]); + } + else + { + isaddr = 0; + len = strlen(tokens[1]); + + for (i=0 ; i 127) || + (c == ',')) + { + return WHITESPACE; + } + + return NOT_WHITESPACE; +} + + +int gettoken (void) +{ + char c; + int count, parencount; + tokenstat stat; + + do + { + if ((c = getchar ()) == EOF) + return FILE_DONE; + + if ((stat = whitespace (c)) == LINE_DONE) + return LINE_DONE; + } while (stat == WHITESPACE); + + token[0] = c; + count = 1; + + if (c == '~') + { + count--; + token[count++] = 'n'; + token[count++] = 'o'; + token[count++] = 't'; + token[count++] = ' '; + } + + if (c == '(') + { + do + { + if ((c = getchar ()) == EOF) + { + fprintf (stderr, "EOF in middle of parentheses\n"); + errorexit (); + } + + token[count++] = c; + + } while (c != ')'); + } + + for ( ;; ) + { + if ((c = getchar ()) == EOF) + { + token[count] = 0; + return TOKEN_AVAILABLE; + } + + if (whitespace (c) == LINE_DONE) + { + if (ungetc (c, stdin) == EOF) + { + fprintf (stderr, "Couldn't unget character\n"); + errorexit (); + } + + token[count] = 0; + return TOKEN_AVAILABLE; + } + + if (whitespace (c) == WHITESPACE) + { + token[count] = 0; + return TOKEN_AVAILABLE; + } + + if (count >= MAX_TOKEN_LENGTH) + { + fprintf (stderr, "Error: token too long\n"); + errorexit (); + } + + token[count++] = c; + + if (c == '~') + { + count--; + token[count++] = 'n'; + token[count++] = 'o'; + token[count++] = 't'; + token[count++] = ' '; + } + else if (c == '(') + { + parencount = 1; + + do + { + if ((c = getchar ()) == EOF) + { + fprintf (stderr, "EOF in middle of parentheses\n"); + errorexit (); + } + + if (c == '(') + parencount++; + else if (c == ')') + parencount--; + + if (c == '~') + { + token[count++] = 'n'; + token[count++] = 'o'; + token[count++] = 't'; + token[count++] = ' '; + } + else + { + token[count++] = c; + } + + } while ((c != ')') || (parencount > 0)); + } + } +} + + +tokenstat parseline (void) +{ + tokenstat stat; + int i, j, firsttoken, labelfound; + int mnemfound; + + firsttoken = 1; + tokennum = 0; + labelfound = 0; + + for ( ;; ) + { + token = tokens[tokennum]; + stat = gettoken (); + + switch (stat) + { + case FILE_DONE: + return FILE_DONE; + + case LINE_DONE: + if (!firsttoken && tokennum) + { + mnemfound = 0; + + for (i=0 ; i 0) && + (parsedata[i].numtokens != tokennum)) || + ((parsedata[i].numtokens < 0) && + (tokennum < -parsedata[i].numtokens))) + { + fprintf (stderr, "mismatched number of tokens\n"); + + for (j=0 ; j= MAX_TOKENS) + { + fprintf (stderr, "Error: too many tokens\n"); + exit (0); + } + + tokennum++; + + break; + + default: + fprintf (stderr, "Error: unknown tokenstat %d\n", stat); + exit (0); + } + } +} + + +void main (int argc, char **argv) +{ + tokenstat stat; + + printf (" .386P\n" + " .model FLAT\n"); + inline = 1; + outline = 3; + + for ( ;; ) + { + stat = parseline (); + inline++; + + switch (stat) + { + case FILE_DONE: + if (currentseg == TEXTSEG) + printf ("_TEXT ENDS\n"); + else if (currentseg == DATASEG) + printf ("_DATA ENDS\n"); + + printf (" END\n"); + exit (0); + + case PARSED_OKAY: + break; + + default: + fprintf (stderr, "Error: unknown tokenstat %d\n", stat); + exit (0); + } + } +} + diff --git a/WinQuake/gas2masm/gas2masm.dsp b/WinQuake/gas2masm/gas2masm.dsp index de661a4..b570d68 100644 --- a/WinQuake/gas2masm/gas2masm.dsp +++ b/WinQuake/gas2masm/gas2masm.dsp @@ -1,100 +1,100 @@ -# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=gas2masm - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "gas2masm.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "gas2masm - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "gas2masm - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\Release" -# PROP BASE Intermediate_Dir ".\Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir ".\Release" -# PROP Intermediate_Dir ".\Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "gas2masm - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir ".\Debug" -# PROP BASE Intermediate_Dir ".\Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir ".\Debug" -# PROP Intermediate_Dir ".\Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 - -!ENDIF - -# Begin Target - -# Name "gas2masm - Win32 Release" -# Name "gas2masm - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=.\gas2masm.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="gas2masm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gas2masm - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gas2masm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gas2masm.mak" CFG="gas2masm - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gas2masm - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "gas2masm - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gas2masm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gas2masm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "gas2masm - Win32 Release" +# Name "gas2masm - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\gas2masm.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/WinQuake/gas2masm/gas2masm.dsw b/WinQuake/gas2masm/gas2masm.dsw index b536254..6c82458 100644 --- a/WinQuake/gas2masm/gas2masm.dsw +++ b/WinQuake/gas2masm/gas2masm.dsw @@ -1,29 +1,29 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "gas2masm"=.\gas2masm.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gas2masm"=.\gas2masm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/WinQuake/gas2masm/gas2masm.plg b/WinQuake/gas2masm/gas2masm.plg index 067e7c7..4475769 100644 --- a/WinQuake/gas2masm/gas2masm.plg +++ b/WinQuake/gas2masm/gas2masm.plg @@ -1,32 +1,32 @@ - - -
-

Build Log

-

---------------------Configuration: gas2masm - Win32 Debug-------------------- -

-

Command Lines

-Creating temporary file "C:\TEMP\RSP730.tmp" with contents -[ -/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fp".\Debug/gas2masm.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c -"D:\Work\quake source\WinQuake\gas2masm\gas2masm.c" -] -Creating command line "cl.exe @C:\TEMP\RSP730.tmp" -Creating temporary file "C:\TEMP\RSP731.tmp" with contents -[ -kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:".\Debug/gas2masm.pdb" /debug /machine:I386 /out:".\Debug/gas2masm.exe" -".\Debug\gas2masm.obj" -] -Creating command line "link.exe @C:\TEMP\RSP731.tmp" -

Output Window

-Compiling... -gas2masm.c -Linking... - - - -

Results

-gas2masm.exe - 0 error(s), 0 warning(s) -
- - + + +
+

Build Log

+

+--------------------Configuration: gas2masm - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\TEMP\RSP730.tmp" with contents +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Fp".\Debug/gas2masm.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c +"D:\Work\quake source\WinQuake\gas2masm\gas2masm.c" +] +Creating command line "cl.exe @C:\TEMP\RSP730.tmp" +Creating temporary file "C:\TEMP\RSP731.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:".\Debug/gas2masm.pdb" /debug /machine:I386 /out:".\Debug/gas2masm.exe" +".\Debug\gas2masm.obj" +] +Creating command line "link.exe @C:\TEMP\RSP731.tmp" +

Output Window

+Compiling... +gas2masm.c +Linking... + + + +

Results

+gas2masm.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/WinQuake/gl_draw.c b/WinQuake/gl_draw.c index 25a8007..61480b4 100644 --- a/WinQuake/gl_draw.c +++ b/WinQuake/gl_draw.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // draw.c -- this is the only file outside the refresh that touches the // vid buffer @@ -1252,7 +1252,7 @@ int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolea } else { glt = &gltextures[numgltextures]; - numgltextures++; + numgltextures++; } strcpy (glt->identifier, identifier); diff --git a/WinQuake/gl_mesh.c b/WinQuake/gl_mesh.c index 100c662..a5ff847 100644 --- a/WinQuake/gl_mesh.c +++ b/WinQuake/gl_mesh.c @@ -1,360 +1,360 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// gl_mesh.c: triangle model functions - -#include "quakedef.h" - -/* -================================================================= - -ALIAS MODEL DISPLAY LIST GENERATION - -================================================================= -*/ - -model_t *aliasmodel; -aliashdr_t *paliashdr; - -qboolean used[8192]; - -// the command list holds counts and s/t values that are valid for -// every frame -int commands[8192]; -int numcommands; - -// all frames will have their vertexes rearranged and expanded -// so they are in the order expected by the command list -int vertexorder[8192]; -int numorder; - -int allverts, alltris; - -int stripverts[128]; -int striptris[128]; -int stripcount; - -/* -================ -StripLength -================ -*/ -int StripLength (int starttri, int startv) -{ - int m1, m2; - int j; - mtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - stripverts[0] = last->vertindex[(startv)%3]; - stripverts[1] = last->vertindex[(startv+1)%3]; - stripverts[2] = last->vertindex[(startv+2)%3]; - - striptris[0] = starttri; - stripcount = 1; - - m1 = last->vertindex[(startv+2)%3]; - m2 = last->vertindex[(startv+1)%3]; - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) - { - if (check->facesfront != last->facesfront) - continue; - for (k=0 ; k<3 ; k++) - { - if (check->vertindex[k] != m1) - continue; - if (check->vertindex[ (k+1)%3 ] != m2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - if (stripcount & 1) - m2 = check->vertindex[ (k+2)%3 ]; - else - m1 = check->vertindex[ (k+2)%3 ]; - - stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; - striptris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) - if (used[j] == 2) - used[j] = 0; - - return stripcount; -} - -/* -=========== -FanLength -=========== -*/ -int FanLength (int starttri, int startv) -{ - int m1, m2; - int j; - mtriangle_t *last, *check; - int k; - - used[starttri] = 2; - - last = &triangles[starttri]; - - stripverts[0] = last->vertindex[(startv)%3]; - stripverts[1] = last->vertindex[(startv+1)%3]; - stripverts[2] = last->vertindex[(startv+2)%3]; - - striptris[0] = starttri; - stripcount = 1; - - m1 = last->vertindex[(startv+0)%3]; - m2 = last->vertindex[(startv+2)%3]; - - - // look for a matching triangle -nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) - { - if (check->facesfront != last->facesfront) - continue; - for (k=0 ; k<3 ; k++) - { - if (check->vertindex[k] != m1) - continue; - if (check->vertindex[ (k+1)%3 ] != m2) - continue; - - // this is the next part of the fan - - // if we can't use this triangle, this tristrip is done - if (used[j]) - goto done; - - // the new edge - m2 = check->vertindex[ (k+2)%3 ]; - - stripverts[stripcount+2] = m2; - striptris[stripcount] = j; - stripcount++; - - used[j] = 2; - goto nexttri; - } - } -done: - - // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) - if (used[j] == 2) - used[j] = 0; - - return stripcount; -} - - -/* -================ -BuildTris - -Generate a list of trifans or strips -for the model, which holds for all frames -================ -*/ -void BuildTris (void) -{ - int i, j, k; - int startv; - mtriangle_t *last, *check; - int m1, m2; - int striplength; - trivertx_t *v; - mtriangle_t *tv; - float s, t; - int index; - int len, bestlen, besttype; - int bestverts[1024]; - int besttris[1024]; - int type; - - // - // build tristrips - // - numorder = 0; - numcommands = 0; - memset (used, 0, sizeof(used)); - for (i=0 ; inumtris ; i++) - { - // pick an unused triangle and start the trifan - if (used[i]) - continue; - - bestlen = 0; - for (type = 0 ; type < 2 ; type++) -// type = 1; - { - for (startv =0 ; startv < 3 ; startv++) - { - if (type == 1) - len = StripLength (i, startv); - else - len = FanLength (i, startv); - if (len > bestlen) - { - besttype = type; - bestlen = len; - for (j=0 ; jskinwidth / 2; // on back side - s = (s + 0.5) / pheader->skinwidth; - t = (t + 0.5) / pheader->skinheight; - - *(float *)&commands[numcommands++] = s; - *(float *)&commands[numcommands++] = t; - } - } - - commands[numcommands++] = 0; // end of list marker - - Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); - - allverts += numorder; - alltris += pheader->numtris; -} - - -/* -================ -GL_MakeAliasModelDisplayLists -================ -*/ -void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) -{ - int i, j; - maliasgroup_t *paliasgroup; - int *cmds; - trivertx_t *verts; - char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c; - FILE *f; - int len; - byte *data; - - aliasmodel = m; - paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); - - // - // look for a cached version - // - strcpy (cache, "glquake/"); - COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); - strcat (cache, ".ms2"); - - COM_FOpenFile (cache, &f); - if (f) - { - fread (&numcommands, 4, 1, f); - fread (&numorder, 4, 1, f); - fread (&commands, numcommands * sizeof(commands[0]), 1, f); - fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); - fclose (f); - } - else - { - // - // build it from scratch - // - Con_Printf ("meshing %s...\n",m->name); - - BuildTris (); // trifans or lists - - // - // save out the cached version - // - sprintf (fullpath, "%s/%s", com_gamedir, cache); - f = fopen (fullpath, "wb"); - if (f) - { - fwrite (&numcommands, 4, 1, f); - fwrite (&numorder, 4, 1, f); - fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); - fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); - fclose (f); - } - } - - - // save the data out - - paliashdr->poseverts = numorder; - - cmds = Hunk_Alloc (numcommands * 4); - paliashdr->commands = (byte *)cmds - (byte *)paliashdr; - memcpy (cmds, commands, numcommands * 4); - - verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts - * sizeof(trivertx_t) ); - paliashdr->posedata = (byte *)verts - (byte *)paliashdr; - for (i=0 ; inumposes ; i++) - for (j=0 ; jvertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+2)%3]; + m2 = last->vertindex[(startv+1)%3]; + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + if (stripcount & 1) + m2 = check->vertindex[ (k+2)%3 ]; + else + m1 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + +/* +=========== +FanLength +=========== +*/ +int FanLength (int starttri, int startv) +{ + int m1, m2; + int j; + mtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + stripverts[0] = last->vertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+0)%3]; + m2 = last->vertindex[(startv+2)%3]; + + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + m2 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = m2; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + + +/* +================ +BuildTris + +Generate a list of trifans or strips +for the model, which holds for all frames +================ +*/ +void BuildTris (void) +{ + int i, j, k; + int startv; + mtriangle_t *last, *check; + int m1, m2; + int striplength; + trivertx_t *v; + mtriangle_t *tv; + float s, t; + int index; + int len, bestlen, besttype; + int bestverts[1024]; + int besttris[1024]; + int type; + + // + // build tristrips + // + numorder = 0; + numcommands = 0; + memset (used, 0, sizeof(used)); + for (i=0 ; inumtris ; i++) + { + // pick an unused triangle and start the trifan + if (used[i]) + continue; + + bestlen = 0; + for (type = 0 ; type < 2 ; type++) +// type = 1; + { + for (startv =0 ; startv < 3 ; startv++) + { + if (type == 1) + len = StripLength (i, startv); + else + len = FanLength (i, startv); + if (len > bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; jskinwidth / 2; // on back side + s = (s + 0.5) / pheader->skinwidth; + t = (t + 0.5) / pheader->skinheight; + + *(float *)&commands[numcommands++] = s; + *(float *)&commands[numcommands++] = t; + } + } + + commands[numcommands++] = 0; // end of list marker + + Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); + + allverts += numorder; + alltris += pheader->numtris; +} + + +/* +================ +GL_MakeAliasModelDisplayLists +================ +*/ +void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) +{ + int i, j; + maliasgroup_t *paliasgroup; + int *cmds; + trivertx_t *verts; + char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c; + FILE *f; + int len; + byte *data; + + aliasmodel = m; + paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); + + // + // look for a cached version + // + strcpy (cache, "glquake/"); + COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); + strcat (cache, ".ms2"); + + COM_FOpenFile (cache, &f); + if (f) + { + fread (&numcommands, 4, 1, f); + fread (&numorder, 4, 1, f); + fread (&commands, numcommands * sizeof(commands[0]), 1, f); + fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); + fclose (f); + } + else + { + // + // build it from scratch + // + Con_Printf ("meshing %s...\n",m->name); + + BuildTris (); // trifans or lists + + // + // save out the cached version + // + sprintf (fullpath, "%s/%s", com_gamedir, cache); + f = fopen (fullpath, "wb"); + if (f) + { + fwrite (&numcommands, 4, 1, f); + fwrite (&numorder, 4, 1, f); + fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); + fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); + fclose (f); + } + } + + + // save the data out + + paliashdr->poseverts = numorder; + + cmds = Hunk_Alloc (numcommands * 4); + paliashdr->commands = (byte *)cmds - (byte *)paliashdr; + memcpy (cmds, commands, numcommands * 4); + + verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts + * sizeof(trivertx_t) ); + paliashdr->posedata = (byte *)verts - (byte *)paliashdr; + for (i=0 ; inumposes ; i++) + for (j=0 ; jsurfedges[], negative numbers - int numedges; // are backwards edges - - short texturemins[2]; - short extents[2]; - - int light_s, light_t; // gl lightmap coordinates - - glpoly_t *polys; // multiple if warped - struct msurface_s *texturechain; - - mtexinfo_t *texinfo; - -// lighting info - int dlightframe; - int dlightbits; - - int lightmaptexturenum; - byte styles[MAXLIGHTMAPS]; - int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap - qboolean cached_dlight; // true if dynamic light in cache - byte *samples; // [numstyles*surfsize] -} msurface_t; - -typedef struct mnode_s -{ -// common with leaf - int contents; // 0, to differentiate from leafs - int visframe; // node needs to be traversed if current - - float minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// node specific - mplane_t *plane; - struct mnode_s *children[2]; - - unsigned short firstsurface; - unsigned short numsurfaces; -} mnode_t; - - - -typedef struct mleaf_s -{ -// common with node - int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current - - float minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// leaf specific - byte *compressed_vis; - efrag_t *efrags; - - msurface_t **firstmarksurface; - int nummarksurfaces; - int key; // BSP sequence number for leaf's contents - byte ambient_sound_level[NUM_AMBIENTS]; -} mleaf_t; - -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct -{ - dclipnode_t *clipnodes; - mplane_t *planes; - int firstclipnode; - int lastclipnode; - vec3_t clip_mins; - vec3_t clip_maxs; -} hull_t; - -/* -============================================================================== - -SPRITE MODELS - -============================================================================== -*/ - - -// FIXME: shorten these? -typedef struct mspriteframe_s -{ - int width; - int height; - float up, down, left, right; - int gl_texturenum; -} mspriteframe_t; - -typedef struct -{ - int numframes; - float *intervals; - mspriteframe_t *frames[1]; -} mspritegroup_t; - -typedef struct -{ - spriteframetype_t type; - mspriteframe_t *frameptr; -} mspriteframedesc_t; - -typedef struct -{ - int type; - int maxwidth; - int maxheight; - int numframes; - float beamlength; // remove? - void *cachespot; // remove? - mspriteframedesc_t frames[1]; -} msprite_t; - - -/* -============================================================================== - -ALIAS MODELS - -Alias models are position independent, so the cache manager can move them. -============================================================================== -*/ - -typedef struct -{ - int firstpose; - int numposes; - float interval; - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; - char name[16]; -} maliasframedesc_t; - -typedef struct -{ - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; -} maliasgroupframedesc_t; - -typedef struct -{ - int numframes; - int intervals; - maliasgroupframedesc_t frames[1]; -} maliasgroup_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct mtriangle_s { - int facesfront; - int vertindex[3]; -} mtriangle_t; - - -#define MAX_SKINS 32 -typedef struct { - int ident; - int version; - vec3_t scale; - vec3_t scale_origin; - float boundingradius; - vec3_t eyeposition; - int numskins; - int skinwidth; - int skinheight; - int numverts; - int numtris; - int numframes; - synctype_t synctype; - int flags; - float size; - - int numposes; - int poseverts; - int posedata; // numposes*poseverts trivert_t - int commands; // gl command list with embedded s/t - int gl_texturenum[MAX_SKINS][4]; - int texels[MAX_SKINS]; // only for player skins - maliasframedesc_t frames[1]; // variable sized -} aliashdr_t; - -#define MAXALIASVERTS 1024 -#define MAXALIASFRAMES 256 -#define MAXALIASTRIS 2048 -extern aliashdr_t *pheader; -extern stvert_t stverts[MAXALIASVERTS]; -extern mtriangle_t triangles[MAXALIASTRIS]; -extern trivertx_t *poseverts[MAXALIASFRAMES]; - -//=================================================================== - -// -// Whole model -// - -typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; - -#define EF_ROCKET 1 // leave a trail -#define EF_GRENADE 2 // leave a trail -#define EF_GIB 4 // leave a trail -#define EF_ROTATE 8 // rotate (bonus items) -#define EF_TRACER 16 // green split trail -#define EF_ZOMGIB 32 // small blood trail -#define EF_TRACER2 64 // orange split trail + rotate -#define EF_TRACER3 128 // purple trail - -typedef struct model_s -{ - char name[MAX_QPATH]; - qboolean needload; // bmodels and sprites don't cache normally - - modtype_t type; - int numframes; - synctype_t synctype; - - int flags; - -// -// volume occupied by the model graphics -// - vec3_t mins, maxs; - float radius; - -// -// solid volume for clipping -// - qboolean clipbox; - vec3_t clipmins, clipmaxs; - -// -// brush model -// - int firstmodelsurface, nummodelsurfaces; - - int numsubmodels; - dmodel_t *submodels; - - int numplanes; - mplane_t *planes; - - int numleafs; // number of visible leafs, not counting 0 - mleaf_t *leafs; - - int numvertexes; - mvertex_t *vertexes; - - int numedges; - medge_t *edges; - - int numnodes; - mnode_t *nodes; - - int numtexinfo; - mtexinfo_t *texinfo; - - int numsurfaces; - msurface_t *surfaces; - - int numsurfedges; - int *surfedges; - - int numclipnodes; - dclipnode_t *clipnodes; - - int nummarksurfaces; - msurface_t **marksurfaces; - - hull_t hulls[MAX_MAP_HULLS]; - - int numtextures; - texture_t **textures; - - byte *visdata; - byte *lightdata; - char *entities; - -// -// additional model data -// - cache_user_t cache; // only access through Mod_Extradata - -} model_t; - -//============================================================================ - -void Mod_Init (void); -void Mod_ClearAll (void); -model_t *Mod_ForName (char *name, qboolean crash); -void *Mod_Extradata (model_t *mod); // handles caching -void Mod_TouchModel (char *name); - -mleaf_t *Mod_PointInLeaf (float *p, model_t *model); -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); - -#endif // __MODEL__ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __MODEL__ +#define __MODEL__ + +#include "modelgen.h" +#include "spritegn.h" + +/* + +d*_t structures are on-disk representations +m*_t structures are in-memory + +*/ + +// entity effects + +#define EF_BRIGHTFIELD 1 +#define EF_MUZZLEFLASH 2 +#define EF_BRIGHTLIGHT 4 +#define EF_DIMLIGHT 8 + + +/* +============================================================================== + +BRUSH MODELS + +============================================================================== +*/ + + +// +// in memory representation +// +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + vec3_t position; +} mvertex_t; + +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 + + +// plane_t structure +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct mplane_s +{ + vec3_t normal; + float dist; + byte type; // for texture axis selection and fast side tests + byte signbits; // signx + signy<<1 + signz<<1 + byte pad[2]; +} mplane_t; + +typedef struct texture_s +{ + char name[16]; + unsigned width, height; + int gl_texturenum; + struct msurface_s *texturechain; // for gl_texsort drawing + int anim_total; // total tenths in sequence ( 0 = no) + int anim_min, anim_max; // time for this frame min <=time< max + struct texture_s *anim_next; // in the animation sequence + struct texture_s *alternate_anims; // bmodels in frmae 1 use these + unsigned offsets[MIPLEVELS]; // four mip maps stored +} texture_t; + + +#define SURF_PLANEBACK 2 +#define SURF_DRAWSKY 4 +#define SURF_DRAWSPRITE 8 +#define SURF_DRAWTURB 0x10 +#define SURF_DRAWTILED 0x20 +#define SURF_DRAWBACKGROUND 0x40 +#define SURF_UNDERWATER 0x80 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + unsigned short v[2]; + unsigned int cachededgeoffset; +} medge_t; + +typedef struct +{ + float vecs[2][4]; + float mipadjust; + texture_t *texture; + int flags; +} mtexinfo_t; + +#define VERTEXSIZE 7 + +typedef struct glpoly_s +{ + struct glpoly_s *next; + struct glpoly_s *chain; + int numverts; + int flags; // for SURF_UNDERWATER + float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) +} glpoly_t; + +typedef struct msurface_s +{ + int visframe; // should be drawn when node is crossed + + mplane_t *plane; + int flags; + + int firstedge; // look up in model->surfedges[], negative numbers + int numedges; // are backwards edges + + short texturemins[2]; + short extents[2]; + + int light_s, light_t; // gl lightmap coordinates + + glpoly_t *polys; // multiple if warped + struct msurface_s *texturechain; + + mtexinfo_t *texinfo; + +// lighting info + int dlightframe; + int dlightbits; + + int lightmaptexturenum; + byte styles[MAXLIGHTMAPS]; + int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap + qboolean cached_dlight; // true if dynamic light in cache + byte *samples; // [numstyles*surfsize] +} msurface_t; + +typedef struct mnode_s +{ +// common with leaf + int contents; // 0, to differentiate from leafs + int visframe; // node needs to be traversed if current + + float minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// node specific + mplane_t *plane; + struct mnode_s *children[2]; + + unsigned short firstsurface; + unsigned short numsurfaces; +} mnode_t; + + + +typedef struct mleaf_s +{ +// common with node + int contents; // wil be a negative contents number + int visframe; // node needs to be traversed if current + + float minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// leaf specific + byte *compressed_vis; + efrag_t *efrags; + + msurface_t **firstmarksurface; + int nummarksurfaces; + int key; // BSP sequence number for leaf's contents + byte ambient_sound_level[NUM_AMBIENTS]; +} mleaf_t; + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + dclipnode_t *clipnodes; + mplane_t *planes; + int firstclipnode; + int lastclipnode; + vec3_t clip_mins; + vec3_t clip_maxs; +} hull_t; + +/* +============================================================================== + +SPRITE MODELS + +============================================================================== +*/ + + +// FIXME: shorten these? +typedef struct mspriteframe_s +{ + int width; + int height; + float up, down, left, right; + int gl_texturenum; +} mspriteframe_t; + +typedef struct +{ + int numframes; + float *intervals; + mspriteframe_t *frames[1]; +} mspritegroup_t; + +typedef struct +{ + spriteframetype_t type; + mspriteframe_t *frameptr; +} mspriteframedesc_t; + +typedef struct +{ + int type; + int maxwidth; + int maxheight; + int numframes; + float beamlength; // remove? + void *cachespot; // remove? + mspriteframedesc_t frames[1]; +} msprite_t; + + +/* +============================================================================== + +ALIAS MODELS + +Alias models are position independent, so the cache manager can move them. +============================================================================== +*/ + +typedef struct +{ + int firstpose; + int numposes; + float interval; + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; + char name[16]; +} maliasframedesc_t; + +typedef struct +{ + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; +} maliasgroupframedesc_t; + +typedef struct +{ + int numframes; + int intervals; + maliasgroupframedesc_t frames[1]; +} maliasgroup_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct mtriangle_s { + int facesfront; + int vertindex[3]; +} mtriangle_t; + + +#define MAX_SKINS 32 +typedef struct { + int ident; + int version; + vec3_t scale; + vec3_t scale_origin; + float boundingradius; + vec3_t eyeposition; + int numskins; + int skinwidth; + int skinheight; + int numverts; + int numtris; + int numframes; + synctype_t synctype; + int flags; + float size; + + int numposes; + int poseverts; + int posedata; // numposes*poseverts trivert_t + int commands; // gl command list with embedded s/t + int gl_texturenum[MAX_SKINS][4]; + int texels[MAX_SKINS]; // only for player skins + maliasframedesc_t frames[1]; // variable sized +} aliashdr_t; + +#define MAXALIASVERTS 1024 +#define MAXALIASFRAMES 256 +#define MAXALIASTRIS 2048 +extern aliashdr_t *pheader; +extern stvert_t stverts[MAXALIASVERTS]; +extern mtriangle_t triangles[MAXALIASTRIS]; +extern trivertx_t *poseverts[MAXALIASFRAMES]; + +//=================================================================== + +// +// Whole model +// + +typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; + +#define EF_ROCKET 1 // leave a trail +#define EF_GRENADE 2 // leave a trail +#define EF_GIB 4 // leave a trail +#define EF_ROTATE 8 // rotate (bonus items) +#define EF_TRACER 16 // green split trail +#define EF_ZOMGIB 32 // small blood trail +#define EF_TRACER2 64 // orange split trail + rotate +#define EF_TRACER3 128 // purple trail + +typedef struct model_s +{ + char name[MAX_QPATH]; + qboolean needload; // bmodels and sprites don't cache normally + + modtype_t type; + int numframes; + synctype_t synctype; + + int flags; + +// +// volume occupied by the model graphics +// + vec3_t mins, maxs; + float radius; + +// +// solid volume for clipping +// + qboolean clipbox; + vec3_t clipmins, clipmaxs; + +// +// brush model +// + int firstmodelsurface, nummodelsurfaces; + + int numsubmodels; + dmodel_t *submodels; + + int numplanes; + mplane_t *planes; + + int numleafs; // number of visible leafs, not counting 0 + mleaf_t *leafs; + + int numvertexes; + mvertex_t *vertexes; + + int numedges; + medge_t *edges; + + int numnodes; + mnode_t *nodes; + + int numtexinfo; + mtexinfo_t *texinfo; + + int numsurfaces; + msurface_t *surfaces; + + int numsurfedges; + int *surfedges; + + int numclipnodes; + dclipnode_t *clipnodes; + + int nummarksurfaces; + msurface_t **marksurfaces; + + hull_t hulls[MAX_MAP_HULLS]; + + int numtextures; + texture_t **textures; + + byte *visdata; + byte *lightdata; + char *entities; + +// +// additional model data +// + cache_user_t cache; // only access through Mod_Extradata + +} model_t; + +//============================================================================ + +void Mod_Init (void); +void Mod_ClearAll (void); +model_t *Mod_ForName (char *name, qboolean crash); +void *Mod_Extradata (model_t *mod); // handles caching +void Mod_TouchModel (char *name); + +mleaf_t *Mod_PointInLeaf (float *p, model_t *model); +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); + +#endif // __MODEL__ diff --git a/WinQuake/gl_refrag.c b/WinQuake/gl_refrag.c index 1b060b3..516960b 100644 --- a/WinQuake/gl_refrag.c +++ b/WinQuake/gl_refrag.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // r_efrag.c -#include "quakedef.h" +#include "quakedef.h" mnode_t *r_pefragtopnode; diff --git a/WinQuake/gl_rlight.c b/WinQuake/gl_rlight.c index 80ada45..6155001 100644 --- a/WinQuake/gl_rlight.c +++ b/WinQuake/gl_rlight.c @@ -1,25 +1,25 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // r_light.c -#include "quakedef.h" +#include "quakedef.h" int r_dlightframecount; @@ -51,96 +51,96 @@ void R_AnimateLight (void) } } -/* -============================================================================= - -DYNAMIC LIGHTS BLEND RENDERING - -============================================================================= -*/ - -void AddLightBlend (float r, float g, float b, float a2) -{ - float a; - - v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]); - - a2 = a2/a; - - v_blend[0] = v_blend[1]*(1-a2) + r*a2; - v_blend[1] = v_blend[1]*(1-a2) + g*a2; - v_blend[2] = v_blend[2]*(1-a2) + b*a2; -} - -void R_RenderDlight (dlight_t *light) -{ - int i, j; - float a; - vec3_t v; - float rad; - - rad = light->radius * 0.35; - - VectorSubtract (light->origin, r_origin, v); - if (Length (v) < rad) - { // view is inside the dlight - AddLightBlend (1, 0.5, 0, light->radius * 0.0003); - return; - } - - glBegin (GL_TRIANGLE_FAN); - glColor3f (0.2,0.1,0.0); - for (i=0 ; i<3 ; i++) - v[i] = light->origin[i] - vpn[i]*rad; - glVertex3fv (v); - glColor3f (0,0,0); - for (i=16 ; i>=0 ; i--) - { - a = i/16.0 * M_PI*2; - for (j=0 ; j<3 ; j++) - v[j] = light->origin[j] + vright[j]*cos(a)*rad - + vup[j]*sin(a)*rad; - glVertex3fv (v); - } - glEnd (); -} - -/* -============= -R_RenderDlights -============= -*/ -void R_RenderDlights (void) -{ - int i; - dlight_t *l; - - if (!gl_flashblend.value) - return; - - r_dlightframecount = r_framecount + 1; // because the count hasn't - // advanced yet for this frame - glDepthMask (0); - glDisable (GL_TEXTURE_2D); - glShadeModel (GL_SMOOTH); - glEnable (GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE); - - l = cl_dlights; - for (i=0 ; idie < cl.time || !l->radius) - continue; - R_RenderDlight (l); - } - - glColor3f (1,1,1); - glDisable (GL_BLEND); - glEnable (GL_TEXTURE_2D); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask (1); -} - +/* +============================================================================= + +DYNAMIC LIGHTS BLEND RENDERING + +============================================================================= +*/ + +void AddLightBlend (float r, float g, float b, float a2) +{ + float a; + + v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]); + + a2 = a2/a; + + v_blend[0] = v_blend[1]*(1-a2) + r*a2; + v_blend[1] = v_blend[1]*(1-a2) + g*a2; + v_blend[2] = v_blend[2]*(1-a2) + b*a2; +} + +void R_RenderDlight (dlight_t *light) +{ + int i, j; + float a; + vec3_t v; + float rad; + + rad = light->radius * 0.35; + + VectorSubtract (light->origin, r_origin, v); + if (Length (v) < rad) + { // view is inside the dlight + AddLightBlend (1, 0.5, 0, light->radius * 0.0003); + return; + } + + glBegin (GL_TRIANGLE_FAN); + glColor3f (0.2,0.1,0.0); + for (i=0 ; i<3 ; i++) + v[i] = light->origin[i] - vpn[i]*rad; + glVertex3fv (v); + glColor3f (0,0,0); + for (i=16 ; i>=0 ; i--) + { + a = i/16.0 * M_PI*2; + for (j=0 ; j<3 ; j++) + v[j] = light->origin[j] + vright[j]*cos(a)*rad + + vup[j]*sin(a)*rad; + glVertex3fv (v); + } + glEnd (); +} + +/* +============= +R_RenderDlights +============= +*/ +void R_RenderDlights (void) +{ + int i; + dlight_t *l; + + if (!gl_flashblend.value) + return; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + glDepthMask (0); + glDisable (GL_TEXTURE_2D); + glShadeModel (GL_SMOOTH); + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + + l = cl_dlights; + for (i=0 ; idie < cl.time || !l->radius) + continue; + R_RenderDlight (l); + } + + glColor3f (1,1,1); + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask (1); +} + /* ============================================================================= @@ -205,9 +205,9 @@ void R_PushDlights (void) { int i; dlight_t *l; - - if (gl_flashblend.value) - return; + + if (gl_flashblend.value) + return; r_dlightframecount = r_framecount + 1; // because the count hasn't // advanced yet for this frame @@ -229,9 +229,9 @@ LIGHT SAMPLING ============================================================================= */ - -mplane_t *lightplane; -vec3_t lightspot; + +mplane_t *lightplane; +vec3_t lightspot; int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) { @@ -276,8 +276,8 @@ int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) return -1; // didn't hit anuthing // check for impact on this node - VectorCopy (mid, lightspot); - lightplane = plane; + VectorCopy (mid, lightspot); + lightplane = plane; surf = cl.worldmodel->surfaces + node->firstsurface; for (i=0 ; inumsurfaces ; i++, surf++) diff --git a/WinQuake/gl_rmain.c b/WinQuake/gl_rmain.c index d9bf41e..b760b71 100644 --- a/WinQuake/gl_rmain.c +++ b/WinQuake/gl_rmain.c @@ -1,1159 +1,1159 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_main.c - -#include "quakedef.h" - -entity_t r_worldentity; - -qboolean r_cache_thrash; // compatability - -vec3_t modelorg, r_entorigin; -entity_t *currententity; - -int r_visframecount; // bumped when going to a new PVS -int r_framecount; // used for dlight push checking - -mplane_t frustum[4]; - -int c_brush_polys, c_alias_polys; - -qboolean envmap; // true during envmap command capture - -int currenttexture = -1; // to avoid unnecessary texture sets - -int cnttextures[2] = {-1, -1}; // cached - -int particletexture; // little dot for particles -int playertextures; // up to 16 color translated skins - -int mirrortexturenum; // quake texturenum, not gltexturenum -qboolean mirror; -mplane_t *mirror_plane; - -// -// view origin -// -vec3_t vup; -vec3_t vpn; -vec3_t vright; -vec3_t r_origin; - -float r_world_matrix[16]; -float r_base_world_matrix[16]; - -// -// screen size info -// -refdef_t r_refdef; - -mleaf_t *r_viewleaf, *r_oldviewleaf; - -texture_t *r_notexture_mip; - -int d_lightstylevalue[256]; // 8.8 fraction of base light value - - -void R_MarkLeaves (void); - -cvar_t r_norefresh = {"r_norefresh","0"}; -cvar_t r_drawentities = {"r_drawentities","1"}; -cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; -cvar_t r_speeds = {"r_speeds","0"}; -cvar_t r_fullbright = {"r_fullbright","0"}; -cvar_t r_lightmap = {"r_lightmap","0"}; -cvar_t r_shadows = {"r_shadows","0"}; -cvar_t r_mirroralpha = {"r_mirroralpha","1"}; -cvar_t r_wateralpha = {"r_wateralpha","1"}; -cvar_t r_dynamic = {"r_dynamic","1"}; -cvar_t r_novis = {"r_novis","0"}; - -cvar_t gl_finish = {"gl_finish","0"}; -cvar_t gl_clear = {"gl_clear","0"}; -cvar_t gl_cull = {"gl_cull","1"}; -cvar_t gl_texsort = {"gl_texsort","1"}; -cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; -cvar_t gl_affinemodels = {"gl_affinemodels","0"}; -cvar_t gl_polyblend = {"gl_polyblend","1"}; -cvar_t gl_flashblend = {"gl_flashblend","1"}; -cvar_t gl_playermip = {"gl_playermip","0"}; -cvar_t gl_nocolors = {"gl_nocolors","0"}; -cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"}; -cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; -cvar_t gl_doubleeyes = {"gl_doubleeys", "1"}; - -extern cvar_t gl_ztrick; - -/* -================= -R_CullBox - -Returns true if the box is completely outside the frustom -================= -*/ -qboolean R_CullBox (vec3_t mins, vec3_t maxs) -{ - int i; - - for (i=0 ; i<4 ; i++) - if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) - return true; - return false; -} - - -void R_RotateForEntity (entity_t *e) -{ - glTranslatef (e->origin[0], e->origin[1], e->origin[2]); - - glRotatef (e->angles[1], 0, 0, 1); - glRotatef (-e->angles[0], 0, 1, 0); - glRotatef (e->angles[2], 1, 0, 0); -} - -/* -============================================================= - - SPRITE MODELS - -============================================================= -*/ - -/* -================ -R_GetSpriteFrame -================ -*/ -mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) -{ - msprite_t *psprite; - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - int i, numframes, frame; - float *pintervals, fullinterval, targettime, time; - - psprite = currententity->model->cache.data; - frame = currententity->frame; - - if ((frame >= psprite->numframes) || (frame < 0)) - { - Con_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) - { - pspriteframe = psprite->frames[frame].frameptr; - } - else - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - - time = cl.time + currententity->syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by 0 - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - - -/* -================= -R_DrawSpriteModel - -================= -*/ -void R_DrawSpriteModel (entity_t *e) -{ - vec3_t point; - mspriteframe_t *frame; - float *up, *right; - vec3_t v_forward, v_right, v_up; - msprite_t *psprite; - - // don't even bother culling, because it's just a single - // polygon without a surface cache - frame = R_GetSpriteFrame (e); - psprite = currententity->model->cache.data; - - if (psprite->type == SPR_ORIENTED) - { // bullet marks on walls - AngleVectors (currententity->angles, v_forward, v_right, v_up); - up = v_up; - right = v_right; - } - else - { // normal sprite - up = vup; - right = vright; - } - - glColor3f (1,1,1); - - GL_DisableMultitexture(); - - GL_Bind(frame->gl_texturenum); - - glEnable (GL_ALPHA_TEST); - glBegin (GL_QUADS); - - glTexCoord2f (0, 1); - VectorMA (e->origin, frame->down, up, point); - VectorMA (point, frame->left, right, point); - glVertex3fv (point); - - glTexCoord2f (0, 0); - VectorMA (e->origin, frame->up, up, point); - VectorMA (point, frame->left, right, point); - glVertex3fv (point); - - glTexCoord2f (1, 0); - VectorMA (e->origin, frame->up, up, point); - VectorMA (point, frame->right, right, point); - glVertex3fv (point); - - glTexCoord2f (1, 1); - VectorMA (e->origin, frame->down, up, point); - VectorMA (point, frame->right, right, point); - glVertex3fv (point); - - glEnd (); - - glDisable (GL_ALPHA_TEST); -} - -/* -============================================================= - - ALIAS MODELS - -============================================================= -*/ - - -#define NUMVERTEXNORMALS 162 - -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "anorms.h" -}; - -vec3_t shadevector; -float shadelight, ambientlight; - -// precalculated dot products for quantized angles -#define SHADEDOT_QUANT 16 -float r_avertexnormal_dots[SHADEDOT_QUANT][256] = -#include "anorm_dots.h" -; - -float *shadedots = r_avertexnormal_dots[0]; - -int lastposenum; - -/* -============= -GL_DrawAliasFrame -============= -*/ -void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum) -{ - float s, t; - float l; - int i, j; - int index; - trivertx_t *v, *verts; - int list; - int *order; - vec3_t point; - float *normal; - int count; - -lastposenum = posenum; - - verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); - verts += posenum * paliashdr->poseverts; - order = (int *)((byte *)paliashdr + paliashdr->commands); - - while (1) - { - // get the vertex count and primitive type - count = *order++; - if (!count) - break; // done - if (count < 0) - { - count = -count; - glBegin (GL_TRIANGLE_FAN); - } - else - glBegin (GL_TRIANGLE_STRIP); - - do - { - // texture coordinates come from the draw list - glTexCoord2f (((float *)order)[0], ((float *)order)[1]); - order += 2; - - // normals and vertexes come from the frame list - l = shadedots[verts->lightnormalindex] * shadelight; - glColor3f (l, l, l); - glVertex3f (verts->v[0], verts->v[1], verts->v[2]); - verts++; - } while (--count); - - glEnd (); - } -} - - -/* -============= -GL_DrawAliasShadow -============= -*/ -extern vec3_t lightspot; - -void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) -{ - float s, t, l; - int i, j; - int index; - trivertx_t *v, *verts; - int list; - int *order; - vec3_t point; - float *normal; - float height, lheight; - int count; - - lheight = currententity->origin[2] - lightspot[2]; - - height = 0; - verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); - verts += posenum * paliashdr->poseverts; - order = (int *)((byte *)paliashdr + paliashdr->commands); - - height = -lheight + 1.0; - - while (1) - { - // get the vertex count and primitive type - count = *order++; - if (!count) - break; // done - if (count < 0) - { - count = -count; - glBegin (GL_TRIANGLE_FAN); - } - else - glBegin (GL_TRIANGLE_STRIP); - - do - { - // texture coordinates come from the draw list - // (skipped for shadows) glTexCoord2fv ((float *)order); - order += 2; - - // normals and vertexes come from the frame list - point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; - point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; - point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; - - point[0] -= shadevector[0]*(point[2]+lheight); - point[1] -= shadevector[1]*(point[2]+lheight); - point[2] = height; -// height -= 0.001; - glVertex3fv (point); - - verts++; - } while (--count); - - glEnd (); - } -} - - - -/* -================= -R_SetupAliasFrame - -================= -*/ -void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr) -{ - int pose, numposes; - float interval; - - if ((frame >= paliashdr->numframes) || (frame < 0)) - { - Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - pose = paliashdr->frames[frame].firstpose; - numposes = paliashdr->frames[frame].numposes; - - if (numposes > 1) - { - interval = paliashdr->frames[frame].interval; - pose += (int)(cl.time / interval) % numposes; - } - - GL_DrawAliasFrame (paliashdr, pose); -} - - - -/* -================= -R_DrawAliasModel - -================= -*/ -void R_DrawAliasModel (entity_t *e) -{ - int i, j; - int lnum; - vec3_t dist; - float add; - model_t *clmodel; - vec3_t mins, maxs; - aliashdr_t *paliashdr; - trivertx_t *verts, *v; - int index; - float s, t, an; - int anim; - - clmodel = currententity->model; - - VectorAdd (currententity->origin, clmodel->mins, mins); - VectorAdd (currententity->origin, clmodel->maxs, maxs); - - if (R_CullBox (mins, maxs)) - return; - - - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // - // get lighting information - // - - ambientlight = shadelight = R_LightPoint (currententity->origin); - - // allways give the gun some light - if (e == &cl.viewent && ambientlight < 24) - ambientlight = shadelight = 24; - - for (lnum=0 ; lnum= cl.time) - { - VectorSubtract (currententity->origin, - cl_dlights[lnum].origin, - dist); - add = cl_dlights[lnum].radius - Length(dist); - - if (add > 0) { - ambientlight += add; - //ZOID models should be affected by dlights as well - shadelight += add; - } - } - } - - // clamp lighting so it doesn't overbright as much - if (ambientlight > 128) - ambientlight = 128; - if (ambientlight + shadelight > 192) - shadelight = 192 - ambientlight; - - // ZOID: never allow players to go totally black - i = currententity - cl_entities; - if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) - if (ambientlight < 8) - ambientlight = shadelight = 8; - - // HACK HACK HACK -- no fullbright colors, so make torches full light - if (!strcmp (clmodel->name, "progs/flame2.mdl") - || !strcmp (clmodel->name, "progs/flame.mdl") ) - ambientlight = shadelight = 256; - - shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; - shadelight = shadelight / 200.0; - - an = e->angles[1]/180*M_PI; - shadevector[0] = cos(-an); - shadevector[1] = sin(-an); - shadevector[2] = 1; - VectorNormalize (shadevector); - - // - // locate the proper data - // - paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); - - c_alias_polys += paliashdr->numtris; - - // - // draw all the triangles - // - - GL_DisableMultitexture(); - - glPushMatrix (); - R_RotateForEntity (e); - - if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); -// double size of eyes, since they are really hard to see in gl - glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); - } else { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); - glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); - } - - anim = (int)(cl.time*10) & 3; - GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); - - // we can't dynamically colormap textures, so they are cached - // seperately for the players. Heads are just uncolored. - if (currententity->colormap != vid.colormap && !gl_nocolors.value) - { - i = currententity - cl_entities; - if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) - GL_Bind(playertextures - 1 + i); - } - - if (gl_smoothmodels.value) - glShadeModel (GL_SMOOTH); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (gl_affinemodels.value) - glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - - R_SetupAliasFrame (currententity->frame, paliashdr); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glShadeModel (GL_FLAT); - if (gl_affinemodels.value) - glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - glPopMatrix (); - - if (r_shadows.value) - { - glPushMatrix (); - R_RotateForEntity (e); - glDisable (GL_TEXTURE_2D); - glEnable (GL_BLEND); - glColor4f (0,0,0,0.5); - GL_DrawAliasShadow (paliashdr, lastposenum); - glEnable (GL_TEXTURE_2D); - glDisable (GL_BLEND); - glColor4f (1,1,1,1); - glPopMatrix (); - } - -} - -//================================================================================== - -/* -============= -R_DrawEntitiesOnList -============= -*/ -void R_DrawEntitiesOnList (void) -{ - int i; - - if (!r_drawentities.value) - return; - - // draw sprites seperately, because of alpha blending - for (i=0 ; imodel->type) - { - case mod_alias: - R_DrawAliasModel (currententity); - break; - - case mod_brush: - R_DrawBrushModel (currententity); - break; - - default: - break; - } - } - - for (i=0 ; imodel->type) - { - case mod_sprite: - R_DrawSpriteModel (currententity); - break; - } - } -} - -/* -============= -R_DrawViewModel -============= -*/ -void R_DrawViewModel (void) -{ - float ambient[4], diffuse[4]; - int j; - int lnum; - vec3_t dist; - float add; - dlight_t *dl; - int ambientlight, shadelight; - - if (!r_drawviewmodel.value) - return; - - if (chase_active.value) - return; - - if (envmap) - return; - - if (!r_drawentities.value) - return; - - if (cl.items & IT_INVISIBILITY) - return; - - if (cl.stats[STAT_HEALTH] <= 0) - return; - - currententity = &cl.viewent; - if (!currententity->model) - return; - - j = R_LightPoint (currententity->origin); - - if (j < 24) - j = 24; // allways give some light on gun - ambientlight = j; - shadelight = j; - -// add dynamic lights - for (lnum=0 ; lnumradius) - continue; - if (!dl->radius) - continue; - if (dl->die < cl.time) - continue; - - VectorSubtract (currententity->origin, dl->origin, dist); - add = dl->radius - Length(dist); - if (add > 0) - ambientlight += add; - } - - ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; - diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; - - // hack the depth range to prevent view model from poking into walls - glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); - R_DrawAliasModel (currententity); - glDepthRange (gldepthmin, gldepthmax); -} - - -/* -============ -R_PolyBlend -============ -*/ -void R_PolyBlend (void) -{ - if (!gl_polyblend.value) - return; - if (!v_blend[3]) - return; - - GL_DisableMultitexture(); - - glDisable (GL_ALPHA_TEST); - glEnable (GL_BLEND); - glDisable (GL_DEPTH_TEST); - glDisable (GL_TEXTURE_2D); - - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - - glColor4fv (v_blend); - - glBegin (GL_QUADS); - - glVertex3f (10, 100, 100); - glVertex3f (10, -100, 100); - glVertex3f (10, -100, -100); - glVertex3f (10, 100, -100); - glEnd (); - - glDisable (GL_BLEND); - glEnable (GL_TEXTURE_2D); - glEnable (GL_ALPHA_TEST); -} - - -int SignbitsForPlane (mplane_t *out) -{ - int bits, j; - - // for fast box on planeside test - - bits = 0; - for (j=0 ; j<3 ; j++) - { - if (out->normal[j] < 0) - bits |= 1< 1) - Cvar_Set ("r_fullbright", "0"); - - R_AnimateLight (); - - r_framecount++; - -// build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, r_origin); - - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - -// current viewleaf - r_oldviewleaf = r_viewleaf; - r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); - - V_SetContentsColor (r_viewleaf->contents); - V_CalcBlend (); - - r_cache_thrash = false; - - c_brush_polys = 0; - c_alias_polys = 0; - -} - - -void MYgluPerspective( GLdouble fovy, GLdouble aspect, - GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmin, xmax, ymin, ymax; - - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; - - xmin = ymin * aspect; - xmax = ymax * aspect; - - glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); -} - - -/* -============= -R_SetupGL -============= -*/ -void R_SetupGL (void) -{ - float screenaspect; - float yfov; - int i; - extern int glwidth, glheight; - int x, x2, y2, y, w, h; - - // - // set up viewpoint - // - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - x = r_refdef.vrect.x * glwidth/vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; - y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; - y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; - - // fudge around because of frac screen scale - if (x > 0) - x--; - if (x2 < glwidth) - x2++; - if (y2 < 0) - y2--; - if (y < glheight) - y++; - - w = x2 - x; - h = y - y2; - - if (envmap) - { - x = y2 = 0; - w = h = 256; - } - - glViewport (glx + x, gly + y2, w, h); - screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; -// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; - MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); - - if (mirror) - { - if (mirror_plane->normal[2]) - glScalef (1, -1, 1); - else - glScalef (-1, 1, 1); - glCullFace(GL_BACK); - } - else - glCullFace(GL_FRONT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); - - glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); - - // - // set drawing parms - // - if (gl_cull.value) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); - - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glEnable(GL_DEPTH_TEST); -} - -/* -================ -R_RenderScene - -r_refdef must be set before the first call -================ -*/ -void R_RenderScene (void) -{ - R_SetupFrame (); - - R_SetFrustum (); - - R_SetupGL (); - - R_MarkLeaves (); // done here so we know if we're in water - - R_DrawWorld (); // adds static entities to the list - - S_ExtraUpdate (); // don't let sound get messed up if going slow - - R_DrawEntitiesOnList (); - - GL_DisableMultitexture(); - - R_RenderDlights (); - - R_DrawParticles (); - -#ifdef GLTEST - Test_Draw (); -#endif - -} - - -/* -============= -R_Clear -============= -*/ -void R_Clear (void) -{ - if (r_mirroralpha.value != 1.0) - { - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - glClear (GL_DEPTH_BUFFER_BIT); - gldepthmin = 0; - gldepthmax = 0.5; - glDepthFunc (GL_LEQUAL); - } - else if (gl_ztrick.value) - { - static int trickframe; - - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT); - - trickframe++; - if (trickframe & 1) - { - gldepthmin = 0; - gldepthmax = 0.49999; - glDepthFunc (GL_LEQUAL); - } - else - { - gldepthmin = 1; - gldepthmax = 0.5; - glDepthFunc (GL_GEQUAL); - } - } - else - { - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - glClear (GL_DEPTH_BUFFER_BIT); - gldepthmin = 0; - gldepthmax = 1; - glDepthFunc (GL_LEQUAL); - } - - glDepthRange (gldepthmin, gldepthmax); -} - -/* -============= -R_Mirror -============= -*/ -void R_Mirror (void) -{ - float d; - msurface_t *s; - entity_t *ent; - - if (!mirror) - return; - - memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); - - d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; - VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); - - d = DotProduct (vpn, mirror_plane->normal); - VectorMA (vpn, -2*d, mirror_plane->normal, vpn); - - r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; - r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; - r_refdef.viewangles[2] = -r_refdef.viewangles[2]; - - ent = &cl_entities[cl.viewentity]; - if (cl_numvisedicts < MAX_VISEDICTS) - { - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; - } - - gldepthmin = 0.5; - gldepthmax = 1; - glDepthRange (gldepthmin, gldepthmax); - glDepthFunc (GL_LEQUAL); - - R_RenderScene (); - R_DrawWaterSurfaces (); - - gldepthmin = 0; - gldepthmax = 0.5; - glDepthRange (gldepthmin, gldepthmax); - glDepthFunc (GL_LEQUAL); - - // blend on top - glEnable (GL_BLEND); - glMatrixMode(GL_PROJECTION); - if (mirror_plane->normal[2]) - glScalef (1,-1,1); - else - glScalef (-1,1,1); - glCullFace(GL_FRONT); - glMatrixMode(GL_MODELVIEW); - - glLoadMatrixf (r_base_world_matrix); - - glColor4f (1,1,1,r_mirroralpha.value); - s = cl.worldmodel->textures[mirrortexturenum]->texturechain; - for ( ; s ; s=s->texturechain) - R_RenderBrushPoly (s); - cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; - glDisable (GL_BLEND); - glColor4f (1,1,1,1); -} - -/* -================ -R_RenderView - -r_refdef must be set before the first call -================ -*/ -void R_RenderView (void) -{ - double time1, time2; - GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20}; - - if (r_norefresh.value) - return; - - if (!r_worldentity.model || !cl.worldmodel) - Sys_Error ("R_RenderView: NULL worldmodel"); - - if (r_speeds.value) - { - glFinish (); - time1 = Sys_FloatTime (); - c_brush_polys = 0; - c_alias_polys = 0; - } - - mirror = false; - - if (gl_finish.value) - glFinish (); - - R_Clear (); - - // render normal view - -/***** Experimental silly looking fog ****** -****** Use r_fullbright if you enable ****** - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogfv(GL_FOG_COLOR, colors); - glFogf(GL_FOG_END, 512.0); - glEnable(GL_FOG); -********************************************/ - - R_RenderScene (); - R_DrawViewModel (); - R_DrawWaterSurfaces (); - -// More fog right here :) -// glDisable(GL_FOG); -// End of all fog code... - - // render mirror view - R_Mirror (); - - R_PolyBlend (); - - if (r_speeds.value) - { -// glFinish (); - time2 = Sys_FloatTime (); - Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); - } -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_main.c + +#include "quakedef.h" + +entity_t r_worldentity; + +qboolean r_cache_thrash; // compatability + +vec3_t modelorg, r_entorigin; +entity_t *currententity; + +int r_visframecount; // bumped when going to a new PVS +int r_framecount; // used for dlight push checking + +mplane_t frustum[4]; + +int c_brush_polys, c_alias_polys; + +qboolean envmap; // true during envmap command capture + +int currenttexture = -1; // to avoid unnecessary texture sets + +int cnttextures[2] = {-1, -1}; // cached + +int particletexture; // little dot for particles +int playertextures; // up to 16 color translated skins + +int mirrortexturenum; // quake texturenum, not gltexturenum +qboolean mirror; +mplane_t *mirror_plane; + +// +// view origin +// +vec3_t vup; +vec3_t vpn; +vec3_t vright; +vec3_t r_origin; + +float r_world_matrix[16]; +float r_base_world_matrix[16]; + +// +// screen size info +// +refdef_t r_refdef; + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +texture_t *r_notexture_mip; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + + +void R_MarkLeaves (void); + +cvar_t r_norefresh = {"r_norefresh","0"}; +cvar_t r_drawentities = {"r_drawentities","1"}; +cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; +cvar_t r_speeds = {"r_speeds","0"}; +cvar_t r_fullbright = {"r_fullbright","0"}; +cvar_t r_lightmap = {"r_lightmap","0"}; +cvar_t r_shadows = {"r_shadows","0"}; +cvar_t r_mirroralpha = {"r_mirroralpha","1"}; +cvar_t r_wateralpha = {"r_wateralpha","1"}; +cvar_t r_dynamic = {"r_dynamic","1"}; +cvar_t r_novis = {"r_novis","0"}; + +cvar_t gl_finish = {"gl_finish","0"}; +cvar_t gl_clear = {"gl_clear","0"}; +cvar_t gl_cull = {"gl_cull","1"}; +cvar_t gl_texsort = {"gl_texsort","1"}; +cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; +cvar_t gl_affinemodels = {"gl_affinemodels","0"}; +cvar_t gl_polyblend = {"gl_polyblend","1"}; +cvar_t gl_flashblend = {"gl_flashblend","1"}; +cvar_t gl_playermip = {"gl_playermip","0"}; +cvar_t gl_nocolors = {"gl_nocolors","0"}; +cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"}; +cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; +cvar_t gl_doubleeyes = {"gl_doubleeys", "1"}; + +extern cvar_t gl_ztrick; + +/* +================= +R_CullBox + +Returns true if the box is completely outside the frustom +================= +*/ +qboolean R_CullBox (vec3_t mins, vec3_t maxs) +{ + int i; + + for (i=0 ; i<4 ; i++) + if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) + return true; + return false; +} + + +void R_RotateForEntity (entity_t *e) +{ + glTranslatef (e->origin[0], e->origin[1], e->origin[2]); + + glRotatef (e->angles[1], 0, 0, 1); + glRotatef (-e->angles[0], 0, 1, 0); + glRotatef (e->angles[2], 1, 0, 0); +} + +/* +============================================================= + + SPRITE MODELS + +============================================================= +*/ + +/* +================ +R_GetSpriteFrame +================ +*/ +mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, numframes, frame; + float *pintervals, fullinterval, targettime, time; + + psprite = currententity->model->cache.data; + frame = currententity->frame; + + if ((frame >= psprite->numframes) || (frame < 0)) + { + Con_Printf ("R_DrawSprite: no such frame %d\n", frame); + frame = 0; + } + + if (psprite->frames[frame].type == SPR_SINGLE) + { + pspriteframe = psprite->frames[frame].frameptr; + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + + time = cl.time + currententity->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + for (i=0 ; i<(numframes-1) ; i++) + { + if (pintervals[i] > targettime) + break; + } + + pspriteframe = pspritegroup->frames[i]; + } + + return pspriteframe; +} + + +/* +================= +R_DrawSpriteModel + +================= +*/ +void R_DrawSpriteModel (entity_t *e) +{ + vec3_t point; + mspriteframe_t *frame; + float *up, *right; + vec3_t v_forward, v_right, v_up; + msprite_t *psprite; + + // don't even bother culling, because it's just a single + // polygon without a surface cache + frame = R_GetSpriteFrame (e); + psprite = currententity->model->cache.data; + + if (psprite->type == SPR_ORIENTED) + { // bullet marks on walls + AngleVectors (currententity->angles, v_forward, v_right, v_up); + up = v_up; + right = v_right; + } + else + { // normal sprite + up = vup; + right = vright; + } + + glColor3f (1,1,1); + + GL_DisableMultitexture(); + + GL_Bind(frame->gl_texturenum); + + glEnable (GL_ALPHA_TEST); + glBegin (GL_QUADS); + + glTexCoord2f (0, 1); + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->left, right, point); + glVertex3fv (point); + + glTexCoord2f (0, 0); + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->left, right, point); + glVertex3fv (point); + + glTexCoord2f (1, 0); + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->right, right, point); + glVertex3fv (point); + + glTexCoord2f (1, 1); + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->right, right, point); + glVertex3fv (point); + + glEnd (); + + glDisable (GL_ALPHA_TEST); +} + +/* +============================================================= + + ALIAS MODELS + +============================================================= +*/ + + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + +vec3_t shadevector; +float shadelight, ambientlight; + +// precalculated dot products for quantized angles +#define SHADEDOT_QUANT 16 +float r_avertexnormal_dots[SHADEDOT_QUANT][256] = +#include "anorm_dots.h" +; + +float *shadedots = r_avertexnormal_dots[0]; + +int lastposenum; + +/* +============= +GL_DrawAliasFrame +============= +*/ +void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum) +{ + float s, t; + float l; + int i, j; + int index; + trivertx_t *v, *verts; + int list; + int *order; + vec3_t point; + float *normal; + int count; + +lastposenum = posenum; + + verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts += posenum * paliashdr->poseverts; + order = (int *)((byte *)paliashdr + paliashdr->commands); + + while (1) + { + // get the vertex count and primitive type + count = *order++; + if (!count) + break; // done + if (count < 0) + { + count = -count; + glBegin (GL_TRIANGLE_FAN); + } + else + glBegin (GL_TRIANGLE_STRIP); + + do + { + // texture coordinates come from the draw list + glTexCoord2f (((float *)order)[0], ((float *)order)[1]); + order += 2; + + // normals and vertexes come from the frame list + l = shadedots[verts->lightnormalindex] * shadelight; + glColor3f (l, l, l); + glVertex3f (verts->v[0], verts->v[1], verts->v[2]); + verts++; + } while (--count); + + glEnd (); + } +} + + +/* +============= +GL_DrawAliasShadow +============= +*/ +extern vec3_t lightspot; + +void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) +{ + float s, t, l; + int i, j; + int index; + trivertx_t *v, *verts; + int list; + int *order; + vec3_t point; + float *normal; + float height, lheight; + int count; + + lheight = currententity->origin[2] - lightspot[2]; + + height = 0; + verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts += posenum * paliashdr->poseverts; + order = (int *)((byte *)paliashdr + paliashdr->commands); + + height = -lheight + 1.0; + + while (1) + { + // get the vertex count and primitive type + count = *order++; + if (!count) + break; // done + if (count < 0) + { + count = -count; + glBegin (GL_TRIANGLE_FAN); + } + else + glBegin (GL_TRIANGLE_STRIP); + + do + { + // texture coordinates come from the draw list + // (skipped for shadows) glTexCoord2fv ((float *)order); + order += 2; + + // normals and vertexes come from the frame list + point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; + point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; + point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; + + point[0] -= shadevector[0]*(point[2]+lheight); + point[1] -= shadevector[1]*(point[2]+lheight); + point[2] = height; +// height -= 0.001; + glVertex3fv (point); + + verts++; + } while (--count); + + glEnd (); + } +} + + + +/* +================= +R_SetupAliasFrame + +================= +*/ +void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr) +{ + int pose, numposes; + float interval; + + if ((frame >= paliashdr->numframes) || (frame < 0)) + { + Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); + frame = 0; + } + + pose = paliashdr->frames[frame].firstpose; + numposes = paliashdr->frames[frame].numposes; + + if (numposes > 1) + { + interval = paliashdr->frames[frame].interval; + pose += (int)(cl.time / interval) % numposes; + } + + GL_DrawAliasFrame (paliashdr, pose); +} + + + +/* +================= +R_DrawAliasModel + +================= +*/ +void R_DrawAliasModel (entity_t *e) +{ + int i, j; + int lnum; + vec3_t dist; + float add; + model_t *clmodel; + vec3_t mins, maxs; + aliashdr_t *paliashdr; + trivertx_t *verts, *v; + int index; + float s, t, an; + int anim; + + clmodel = currententity->model; + + VectorAdd (currententity->origin, clmodel->mins, mins); + VectorAdd (currententity->origin, clmodel->maxs, maxs); + + if (R_CullBox (mins, maxs)) + return; + + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // + // get lighting information + // + + ambientlight = shadelight = R_LightPoint (currententity->origin); + + // allways give the gun some light + if (e == &cl.viewent && ambientlight < 24) + ambientlight = shadelight = 24; + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + + if (add > 0) { + ambientlight += add; + //ZOID models should be affected by dlights as well + shadelight += add; + } + } + } + + // clamp lighting so it doesn't overbright as much + if (ambientlight > 128) + ambientlight = 128; + if (ambientlight + shadelight > 192) + shadelight = 192 - ambientlight; + + // ZOID: never allow players to go totally black + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) + if (ambientlight < 8) + ambientlight = shadelight = 8; + + // HACK HACK HACK -- no fullbright colors, so make torches full light + if (!strcmp (clmodel->name, "progs/flame2.mdl") + || !strcmp (clmodel->name, "progs/flame.mdl") ) + ambientlight = shadelight = 256; + + shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; + shadelight = shadelight / 200.0; + + an = e->angles[1]/180*M_PI; + shadevector[0] = cos(-an); + shadevector[1] = sin(-an); + shadevector[2] = 1; + VectorNormalize (shadevector); + + // + // locate the proper data + // + paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); + + c_alias_polys += paliashdr->numtris; + + // + // draw all the triangles + // + + GL_DisableMultitexture(); + + glPushMatrix (); + R_RotateForEntity (e); + + if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { + glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); +// double size of eyes, since they are really hard to see in gl + glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); + } else { + glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + } + + anim = (int)(cl.time*10) & 3; + GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); + + // we can't dynamically colormap textures, so they are cached + // seperately for the players. Heads are just uncolored. + if (currententity->colormap != vid.colormap && !gl_nocolors.value) + { + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) + GL_Bind(playertextures - 1 + i); + } + + if (gl_smoothmodels.value) + glShadeModel (GL_SMOOTH); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + R_SetupAliasFrame (currententity->frame, paliashdr); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glShadeModel (GL_FLAT); + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glPopMatrix (); + + if (r_shadows.value) + { + glPushMatrix (); + R_RotateForEntity (e); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glColor4f (0,0,0,0.5); + GL_DrawAliasShadow (paliashdr, lastposenum); + glEnable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + glColor4f (1,1,1,1); + glPopMatrix (); + } + +} + +//================================================================================== + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i; + + if (!r_drawentities.value) + return; + + // draw sprites seperately, because of alpha blending + for (i=0 ; imodel->type) + { + case mod_alias: + R_DrawAliasModel (currententity); + break; + + case mod_brush: + R_DrawBrushModel (currententity); + break; + + default: + break; + } + } + + for (i=0 ; imodel->type) + { + case mod_sprite: + R_DrawSpriteModel (currententity); + break; + } + } +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ + float ambient[4], diffuse[4]; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + int ambientlight, shadelight; + + if (!r_drawviewmodel.value) + return; + + if (chase_active.value) + return; + + if (envmap) + return; + + if (!r_drawentities.value) + return; + + if (cl.items & IT_INVISIBILITY) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // allways give some light on gun + ambientlight = j; + shadelight = j; + +// add dynamic lights + for (lnum=0 ; lnumradius) + continue; + if (!dl->radius) + continue; + if (dl->die < cl.time) + continue; + + VectorSubtract (currententity->origin, dl->origin, dist); + add = dl->radius - Length(dist); + if (add > 0) + ambientlight += add; + } + + ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; + diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; + + // hack the depth range to prevent view model from poking into walls + glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + R_DrawAliasModel (currententity); + glDepthRange (gldepthmin, gldepthmax); +} + + +/* +============ +R_PolyBlend +============ +*/ +void R_PolyBlend (void) +{ + if (!gl_polyblend.value) + return; + if (!v_blend[3]) + return; + + GL_DisableMultitexture(); + + glDisable (GL_ALPHA_TEST); + glEnable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glDisable (GL_TEXTURE_2D); + + glLoadIdentity (); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + + glColor4fv (v_blend); + + glBegin (GL_QUADS); + + glVertex3f (10, 100, 100); + glVertex3f (10, -100, 100); + glVertex3f (10, -100, -100); + glVertex3f (10, 100, -100); + glEnd (); + + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glEnable (GL_ALPHA_TEST); +} + + +int SignbitsForPlane (mplane_t *out) +{ + int bits, j; + + // for fast box on planeside test + + bits = 0; + for (j=0 ; j<3 ; j++) + { + if (out->normal[j] < 0) + bits |= 1< 1) + Cvar_Set ("r_fullbright", "0"); + + R_AnimateLight (); + + r_framecount++; + +// build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + +// current viewleaf + r_oldviewleaf = r_viewleaf; + r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + + V_SetContentsColor (r_viewleaf->contents); + V_CalcBlend (); + + r_cache_thrash = false; + + c_brush_polys = 0; + c_alias_polys = 0; + +} + + +void MYgluPerspective( GLdouble fovy, GLdouble aspect, + GLdouble zNear, GLdouble zFar ) +{ + GLdouble xmin, xmax, ymin, ymax; + + ymax = zNear * tan( fovy * M_PI / 360.0 ); + ymin = -ymax; + + xmin = ymin * aspect; + xmax = ymax * aspect; + + glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); +} + + +/* +============= +R_SetupGL +============= +*/ +void R_SetupGL (void) +{ + float screenaspect; + float yfov; + int i; + extern int glwidth, glheight; + int x, x2, y2, y, w, h; + + // + // set up viewpoint + // + glMatrixMode(GL_PROJECTION); + glLoadIdentity (); + x = r_refdef.vrect.x * glwidth/vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; + y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; + y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; + + // fudge around because of frac screen scale + if (x > 0) + x--; + if (x2 < glwidth) + x2++; + if (y2 < 0) + y2--; + if (y < glheight) + y++; + + w = x2 - x; + h = y - y2; + + if (envmap) + { + x = y2 = 0; + w = h = 256; + } + + glViewport (glx + x, gly + y2, w, h); + screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; +// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; + MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); + + if (mirror) + { + if (mirror_plane->normal[2]) + glScalef (1, -1, 1); + else + glScalef (-1, 1, 1); + glCullFace(GL_BACK); + } + else + glCullFace(GL_FRONT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity (); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + glRotatef (-r_refdef.viewangles[2], 1, 0, 0); + glRotatef (-r_refdef.viewangles[0], 0, 1, 0); + glRotatef (-r_refdef.viewangles[1], 0, 0, 1); + glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); + + glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); + + // + // set drawing parms + // + if (gl_cull.value) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); +} + +/* +================ +R_RenderScene + +r_refdef must be set before the first call +================ +*/ +void R_RenderScene (void) +{ + R_SetupFrame (); + + R_SetFrustum (); + + R_SetupGL (); + + R_MarkLeaves (); // done here so we know if we're in water + + R_DrawWorld (); // adds static entities to the list + + S_ExtraUpdate (); // don't let sound get messed up if going slow + + R_DrawEntitiesOnList (); + + GL_DisableMultitexture(); + + R_RenderDlights (); + + R_DrawParticles (); + +#ifdef GLTEST + Test_Draw (); +#endif + +} + + +/* +============= +R_Clear +============= +*/ +void R_Clear (void) +{ + if (r_mirroralpha.value != 1.0) + { + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear (GL_DEPTH_BUFFER_BIT); + gldepthmin = 0; + gldepthmax = 0.5; + glDepthFunc (GL_LEQUAL); + } + else if (gl_ztrick.value) + { + static int trickframe; + + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT); + + trickframe++; + if (trickframe & 1) + { + gldepthmin = 0; + gldepthmax = 0.49999; + glDepthFunc (GL_LEQUAL); + } + else + { + gldepthmin = 1; + gldepthmax = 0.5; + glDepthFunc (GL_GEQUAL); + } + } + else + { + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear (GL_DEPTH_BUFFER_BIT); + gldepthmin = 0; + gldepthmax = 1; + glDepthFunc (GL_LEQUAL); + } + + glDepthRange (gldepthmin, gldepthmax); +} + +/* +============= +R_Mirror +============= +*/ +void R_Mirror (void) +{ + float d; + msurface_t *s; + entity_t *ent; + + if (!mirror) + return; + + memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); + + d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; + VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); + + d = DotProduct (vpn, mirror_plane->normal); + VectorMA (vpn, -2*d, mirror_plane->normal, vpn); + + r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; + r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; + r_refdef.viewangles[2] = -r_refdef.viewangles[2]; + + ent = &cl_entities[cl.viewentity]; + if (cl_numvisedicts < MAX_VISEDICTS) + { + cl_visedicts[cl_numvisedicts] = ent; + cl_numvisedicts++; + } + + gldepthmin = 0.5; + gldepthmax = 1; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + R_RenderScene (); + R_DrawWaterSurfaces (); + + gldepthmin = 0; + gldepthmax = 0.5; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + // blend on top + glEnable (GL_BLEND); + glMatrixMode(GL_PROJECTION); + if (mirror_plane->normal[2]) + glScalef (1,-1,1); + else + glScalef (-1,1,1); + glCullFace(GL_FRONT); + glMatrixMode(GL_MODELVIEW); + + glLoadMatrixf (r_base_world_matrix); + + glColor4f (1,1,1,r_mirroralpha.value); + s = cl.worldmodel->textures[mirrortexturenum]->texturechain; + for ( ; s ; s=s->texturechain) + R_RenderBrushPoly (s); + cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; + glDisable (GL_BLEND); + glColor4f (1,1,1,1); +} + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView (void) +{ + double time1, time2; + GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20}; + + if (r_norefresh.value) + return; + + if (!r_worldentity.model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (r_speeds.value) + { + glFinish (); + time1 = Sys_FloatTime (); + c_brush_polys = 0; + c_alias_polys = 0; + } + + mirror = false; + + if (gl_finish.value) + glFinish (); + + R_Clear (); + + // render normal view + +/***** Experimental silly looking fog ****** +****** Use r_fullbright if you enable ****** + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, colors); + glFogf(GL_FOG_END, 512.0); + glEnable(GL_FOG); +********************************************/ + + R_RenderScene (); + R_DrawViewModel (); + R_DrawWaterSurfaces (); + +// More fog right here :) +// glDisable(GL_FOG); +// End of all fog code... + + // render mirror view + R_Mirror (); + + R_PolyBlend (); + + if (r_speeds.value) + { +// glFinish (); + time2 = Sys_FloatTime (); + Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); + } +} diff --git a/WinQuake/gl_rmisc.c b/WinQuake/gl_rmisc.c index c9719b5..caffd83 100644 --- a/WinQuake/gl_rmisc.c +++ b/WinQuake/gl_rmisc.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // r_misc.c #include "quakedef.h" diff --git a/WinQuake/gl_rsurf.c b/WinQuake/gl_rsurf.c index 11b5a01..572228f 100644 --- a/WinQuake/gl_rsurf.c +++ b/WinQuake/gl_rsurf.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // r_surf.c: surface-related refresh code #include "quakedef.h" diff --git a/WinQuake/gl_screen.c b/WinQuake/gl_screen.c index 8a0c096..cd43d17 100644 --- a/WinQuake/gl_screen.c +++ b/WinQuake/gl_screen.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // screen.c -- master for refresh, status bar, console, chat, notify, etc @@ -852,7 +852,7 @@ void SCR_UpdateScreen (void) // determine size of refresh window // if (oldfov != scr_fov.value) - { + { oldfov = scr_fov.value; vid.recalc_refdef = true; } diff --git a/WinQuake/gl_test.c b/WinQuake/gl_test.c index a3b1027..c646a7b 100644 --- a/WinQuake/gl_test.c +++ b/WinQuake/gl_test.c @@ -1,182 +1,182 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - -#ifdef GLTEST - -typedef struct -{ - plane_t *plane; - vec3_t origin; - vec3_t normal; - vec3_t up; - vec3_t right; - vec3_t reflect; - float length; -} puff_t; - -#define MAX_PUFFS 64 - -puff_t puffs[MAX_PUFFS]; - - -void Test_Init (void) -{ -} - - - -plane_t junk; -plane_t *HitPlane (vec3_t start, vec3_t end) -{ - trace_t trace; - -// fill in a default trace - memset (&trace, 0, sizeof(trace_t)); - trace.fraction = 1; - trace.allsolid = true; - VectorCopy (end, trace.endpos); - - SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); - - junk = trace.plane; - return &junk; -} - -void Test_Spawn (vec3_t origin) -{ - int i; - puff_t *p; - vec3_t temp; - vec3_t normal; - vec3_t incoming; - plane_t *plane; - float d; - - for (i=0,p=puffs ; ilength <= 0) - break; - } - if (i == MAX_PUFFS) - return; - - VectorSubtract (r_refdef.vieworg, origin, incoming); - VectorSubtract (origin, incoming, temp); - plane = HitPlane (r_refdef.vieworg, temp); - - VectorNormalize (incoming); - d = DotProduct (incoming, plane->normal); - VectorSubtract (vec3_origin, incoming, p->reflect); - VectorMA (p->reflect, d*2, plane->normal, p->reflect); - - VectorCopy (origin, p->origin); - VectorCopy (plane->normal, p->normal); - - CrossProduct (incoming, p->normal, p->up); - - CrossProduct (p->up, p->normal, p->right); - - p->length = 8; -} - -void DrawPuff (puff_t *p) -{ - vec3_t pts[2][3]; - int i, j; - float s, d; - - for (i=0 ; i<2 ; i++) - { - if (i == 1) - { - s = 6; - d = p->length; - } - else - { - s = 2; - d = 0; - } - - for (j=0 ; j<3 ; j++) - { - pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d; - pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d; - pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d; - } - } - - glColor3f (1, 0, 0); - -#if 0 - glBegin (GL_LINES); - glVertex3fv (p->origin); - glVertex3f (p->origin[0] + p->length*p->reflect[0], - p->origin[1] + p->length*p->reflect[1], - p->origin[2] + p->length*p->reflect[2]); - - glVertex3fv (pts[0][0]); - glVertex3fv (pts[1][0]); - - glVertex3fv (pts[0][1]); - glVertex3fv (pts[1][1]); - - glVertex3fv (pts[0][2]); - glVertex3fv (pts[1][2]); - - glEnd (); -#endif - - glBegin (GL_QUADS); - for (i=0 ; i<3 ; i++) - { - j = (i+1)%3; - glVertex3fv (pts[0][j]); - glVertex3fv (pts[1][j]); - glVertex3fv (pts[1][i]); - glVertex3fv (pts[0][i]); - } - glEnd (); - - glBegin (GL_TRIANGLES); - glVertex3fv (pts[1][0]); - glVertex3fv (pts[1][1]); - glVertex3fv (pts[1][2]); - glEnd (); - - p->length -= host_frametime*2; -} - - -void Test_Draw (void) -{ - int i; - puff_t *p; - - for (i=0, p=puffs ; ilength > 0) - DrawPuff (p); - } -} - -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +#ifdef GLTEST + +typedef struct +{ + plane_t *plane; + vec3_t origin; + vec3_t normal; + vec3_t up; + vec3_t right; + vec3_t reflect; + float length; +} puff_t; + +#define MAX_PUFFS 64 + +puff_t puffs[MAX_PUFFS]; + + +void Test_Init (void) +{ +} + + + +plane_t junk; +plane_t *HitPlane (vec3_t start, vec3_t end) +{ + trace_t trace; + +// fill in a default trace + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + trace.allsolid = true; + VectorCopy (end, trace.endpos); + + SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); + + junk = trace.plane; + return &junk; +} + +void Test_Spawn (vec3_t origin) +{ + int i; + puff_t *p; + vec3_t temp; + vec3_t normal; + vec3_t incoming; + plane_t *plane; + float d; + + for (i=0,p=puffs ; ilength <= 0) + break; + } + if (i == MAX_PUFFS) + return; + + VectorSubtract (r_refdef.vieworg, origin, incoming); + VectorSubtract (origin, incoming, temp); + plane = HitPlane (r_refdef.vieworg, temp); + + VectorNormalize (incoming); + d = DotProduct (incoming, plane->normal); + VectorSubtract (vec3_origin, incoming, p->reflect); + VectorMA (p->reflect, d*2, plane->normal, p->reflect); + + VectorCopy (origin, p->origin); + VectorCopy (plane->normal, p->normal); + + CrossProduct (incoming, p->normal, p->up); + + CrossProduct (p->up, p->normal, p->right); + + p->length = 8; +} + +void DrawPuff (puff_t *p) +{ + vec3_t pts[2][3]; + int i, j; + float s, d; + + for (i=0 ; i<2 ; i++) + { + if (i == 1) + { + s = 6; + d = p->length; + } + else + { + s = 2; + d = 0; + } + + for (j=0 ; j<3 ; j++) + { + pts[i][0][j] = p->origin[j] + p->up[j]*s + p->reflect[j]*d; + pts[i][1][j] = p->origin[j] + p->right[j]*s + p->reflect[j]*d; + pts[i][2][j] = p->origin[j] + -p->right[j]*s + p->reflect[j]*d; + } + } + + glColor3f (1, 0, 0); + +#if 0 + glBegin (GL_LINES); + glVertex3fv (p->origin); + glVertex3f (p->origin[0] + p->length*p->reflect[0], + p->origin[1] + p->length*p->reflect[1], + p->origin[2] + p->length*p->reflect[2]); + + glVertex3fv (pts[0][0]); + glVertex3fv (pts[1][0]); + + glVertex3fv (pts[0][1]); + glVertex3fv (pts[1][1]); + + glVertex3fv (pts[0][2]); + glVertex3fv (pts[1][2]); + + glEnd (); +#endif + + glBegin (GL_QUADS); + for (i=0 ; i<3 ; i++) + { + j = (i+1)%3; + glVertex3fv (pts[0][j]); + glVertex3fv (pts[1][j]); + glVertex3fv (pts[1][i]); + glVertex3fv (pts[0][i]); + } + glEnd (); + + glBegin (GL_TRIANGLES); + glVertex3fv (pts[1][0]); + glVertex3fv (pts[1][1]); + glVertex3fv (pts[1][2]); + glEnd (); + + p->length -= host_frametime*2; +} + + +void Test_Draw (void) +{ + int i; + puff_t *p; + + for (i=0, p=puffs ; ilength > 0) + DrawPuff (p); + } +} + +#endif diff --git a/WinQuake/gl_vidlinux.c b/WinQuake/gl_vidlinux.c index c29f042..d2b7646 100644 --- a/WinQuake/gl_vidlinux.c +++ b/WinQuake/gl_vidlinux.c @@ -1,866 +1,866 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/*#include "vga.h" */ -#include "vgakeyboard.h" -#include "vgamouse.h" - -#include "quakedef.h" -#include "GL/fxmesa.h" - -#define WARP_WIDTH 320 -#define WARP_HEIGHT 200 - -static fxMesaContext fc = NULL; -#define stringify(m) { #m, m } - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; -unsigned char d_15to8table[65536]; - -int num_shades=32; - -struct -{ - char *name; - int num; -} mice[] = -{ - stringify(MOUSE_MICROSOFT), - stringify(MOUSE_MOUSESYSTEMS), - stringify(MOUSE_MMSERIES), - stringify(MOUSE_LOGITECH), - stringify(MOUSE_BUSMOUSE), - stringify(MOUSE_PS2), -}; - -static unsigned char scantokey[128]; - -int num_mice = sizeof (mice) / sizeof(mice[0]); - -int d_con_indirect = 0; - -int svgalib_inited=0; -int UseMouse = 1; -int UseKeyboard = 1; - -int mouserate = MOUSE_DEFAULTSAMPLERATE; - -cvar_t vid_mode = {"vid_mode","5",false}; -cvar_t vid_redrawfull = {"vid_redrawfull","0",false}; -cvar_t vid_waitforrefresh = {"vid_waitforrefresh","0",true}; - -char *framebuffer_ptr; - -cvar_t mouse_button_commands[3] = -{ - {"mouse1","+attack"}, - {"mouse2","+strafe"}, - {"mouse3","+forward"}, -}; - -int mouse_buttons; -int mouse_buttonstate; -int mouse_oldbuttonstate; -float mouse_x, mouse_y; -float old_mouse_x, old_mouse_y; -int mx, my; - -cvar_t m_filter = {"m_filter","1"}; - -int scr_width, scr_height; - -/*-----------------------------------------------------------------------*/ - -//int texture_mode = GL_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; -int texture_mode = GL_LINEAR; -//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; -//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; - -int texture_extension_number = 1; - -float gldepthmin, gldepthmax; - -cvar_t gl_ztrick = {"gl_ztrick","1"}; - -const char *gl_vendor; -const char *gl_renderer; -const char *gl_version; -const char *gl_extensions; - -void (*qgl3DfxSetPaletteEXT) (GLuint *); -void (*qglColorTableEXT) (int, int, int, int, int, const void *); - -static float vid_gamma = 1.0; - -qboolean is8bit = false; -qboolean isPermedia = false; -qboolean gl_mtexable = false; - -/*-----------------------------------------------------------------------*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ -} - -void D_EndDirectRect (int x, int y, int width, int height) -{ -} - -int matchmouse(int mouse, char *name) -{ - int i; - for (i=0 ; i> 2)+4; - b = ((i & 0x7C00) >> 7)+4; - pal = (unsigned char *)d_8to24table; - for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) { - r1 = (int)r - (int)pal[0]; - g1 = (int)g - (int)pal[1]; - b1 = (int)b - (int)pal[2]; - dist = (r1*r1)+(g1*g1)+(b1*b1); - if (dist < bestdist) { - k=v; - bestdist = dist; - } - } - d_15to8table[i]=k; - } -} - -void CheckMultiTextureExtensions(void) -{ - void *prjobj; - - if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { - Con_Printf("Found GL_SGIS_multitexture...\n"); - - if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { - Con_Printf("Unable to open symbol list for main program.\n"); - return; - } - - qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS"); - qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS"); - - if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) { - Con_Printf("Multitexture extensions found.\n"); - gl_mtexable = true; - } else - Con_Printf("Symbol not found, disabled.\n"); - - dlclose(prjobj); - } -} - -/* -=============== -GL_Init -=============== -*/ -void GL_Init (void) -{ - gl_vendor = glGetString (GL_VENDOR); - Con_Printf ("GL_VENDOR: %s\n", gl_vendor); - gl_renderer = glGetString (GL_RENDERER); - Con_Printf ("GL_RENDERER: %s\n", gl_renderer); - - gl_version = glGetString (GL_VERSION); - Con_Printf ("GL_VERSION: %s\n", gl_version); - gl_extensions = glGetString (GL_EXTENSIONS); - Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); - -// Con_Printf ("%s %s\n", gl_renderer, gl_version); - - CheckMultiTextureExtensions (); - - glClearColor (1,0,0,0); - glCullFace(GL_FRONT); - glEnable(GL_TEXTURE_2D); - - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.666); - - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glShadeModel (GL_FLAT); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -} - -/* -================= -GL_BeginRendering - -================= -*/ -void GL_BeginRendering (int *x, int *y, int *width, int *height) -{ - extern cvar_t gl_clear; - - *x = *y = 0; - *width = scr_width; - *height = scr_height; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); -} - - -void GL_EndRendering (void) -{ - glFlush(); - fxMesaSwapBuffers(); -} - -void Init_KBD(void) -{ - int i; - - if (COM_CheckParm("-nokbd")) UseKeyboard = 0; - - if (UseKeyboard) - { - for (i=0 ; i<128 ; i++) - scantokey[i] = ' '; - - scantokey[42] = K_SHIFT; - scantokey[54] = K_SHIFT; - scantokey[72] = K_UPARROW; - scantokey[103] = K_UPARROW; - scantokey[80] = K_DOWNARROW; - scantokey[108] = K_DOWNARROW; - scantokey[75] = K_LEFTARROW; - scantokey[105] = K_LEFTARROW; - scantokey[77] = K_RIGHTARROW; - scantokey[106] = K_RIGHTARROW; - scantokey[29] = K_CTRL; - scantokey[97] = K_CTRL; - scantokey[56] = K_ALT; - scantokey[100] = K_ALT; -// scantokey[58] = JK_CAPS; -// scantokey[69] = JK_NUM_LOCK; - scantokey[71] = K_HOME; - scantokey[73] = K_PGUP; - scantokey[79] = K_END; - scantokey[81] = K_PGDN; - scantokey[82] = K_INS; - scantokey[83] = K_DEL; - scantokey[1 ] = K_ESCAPE; - scantokey[28] = K_ENTER; - scantokey[15] = K_TAB; - scantokey[14] = K_BACKSPACE; - scantokey[119] = K_PAUSE; - scantokey[57] = ' '; - - scantokey[102] = K_HOME; - scantokey[104] = K_PGUP; - scantokey[107] = K_END; - scantokey[109] = K_PGDN; - scantokey[110] = K_INS; - scantokey[111] = K_DEL; - - scantokey[2] = '1'; - scantokey[3] = '2'; - scantokey[4] = '3'; - scantokey[5] = '4'; - scantokey[6] = '5'; - scantokey[7] = '6'; - scantokey[8] = '7'; - scantokey[9] = '8'; - scantokey[10] = '9'; - scantokey[11] = '0'; - scantokey[12] = '-'; - scantokey[13] = '='; - scantokey[41] = '`'; - scantokey[26] = '['; - scantokey[27] = ']'; - scantokey[39] = ';'; - scantokey[40] = '\''; - scantokey[51] = ','; - scantokey[52] = '.'; - scantokey[53] = '/'; - scantokey[43] = '\\'; - - scantokey[59] = K_F1; - scantokey[60] = K_F2; - scantokey[61] = K_F3; - scantokey[62] = K_F4; - scantokey[63] = K_F5; - scantokey[64] = K_F6; - scantokey[65] = K_F7; - scantokey[66] = K_F8; - scantokey[67] = K_F9; - scantokey[68] = K_F10; - scantokey[87] = K_F11; - scantokey[88] = K_F12; - scantokey[30] = 'a'; - scantokey[48] = 'b'; - scantokey[46] = 'c'; - scantokey[32] = 'd'; - scantokey[18] = 'e'; - scantokey[33] = 'f'; - scantokey[34] = 'g'; - scantokey[35] = 'h'; - scantokey[23] = 'i'; - scantokey[36] = 'j'; - scantokey[37] = 'k'; - scantokey[38] = 'l'; - scantokey[50] = 'm'; - scantokey[49] = 'n'; - scantokey[24] = 'o'; - scantokey[25] = 'p'; - scantokey[16] = 'q'; - scantokey[19] = 'r'; - scantokey[31] = 's'; - scantokey[20] = 't'; - scantokey[22] = 'u'; - scantokey[47] = 'v'; - scantokey[17] = 'w'; - scantokey[45] = 'x'; - scantokey[21] = 'y'; - scantokey[44] = 'z'; - - scantokey[78] = '+'; - scantokey[74] = '-'; - - if (keyboard_init()) - Sys_Error("keyboard_init() failed"); - keyboard_seteventhandler(keyhandler); - } -} - -#define NUM_RESOLUTIONS 16 - -static int resolutions[NUM_RESOLUTIONS][3]={ - 320,200, GR_RESOLUTION_320x200, - 320,240, GR_RESOLUTION_320x240, - 400,256, GR_RESOLUTION_400x256, - 400,300, GR_RESOLUTION_400x300, - 512,384, GR_RESOLUTION_512x384, - 640,200, GR_RESOLUTION_640x200, - 640,350, GR_RESOLUTION_640x350, - 640,400, GR_RESOLUTION_640x400, - 640,480, GR_RESOLUTION_640x480, - 800,600, GR_RESOLUTION_800x600, - 960,720, GR_RESOLUTION_960x720, - 856,480, GR_RESOLUTION_856x480, - 512,256, GR_RESOLUTION_512x256, - 1024,768, GR_RESOLUTION_1024x768, - 1280,1024,GR_RESOLUTION_1280x1024, - 1600,1200,GR_RESOLUTION_1600x1200 -}; - -int findres(int *width, int *height) -{ - int i; - - for(i=0;i 255) - inf = 255; - palette[i] = inf; - } - - memcpy (pal, palette, sizeof(palette)); -} - -void VID_Init(unsigned char *palette) -{ - int i; - GLint attribs[32]; - char gldir[MAX_OSPATH]; - int width = 640, height = 480; - - Init_KBD(); - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_redrawfull); - Cvar_RegisterVariable (&vid_waitforrefresh); - Cvar_RegisterVariable (&gl_ztrick); - - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - -// interpret command-line params - -// set vid parameters - attribs[0] = FXMESA_DOUBLEBUFFER; - attribs[1] = FXMESA_ALPHA_SIZE; - attribs[2] = 1; - attribs[3] = FXMESA_DEPTH_SIZE; - attribs[4] = 1; - attribs[5] = FXMESA_NONE; - - if ((i = COM_CheckParm("-width")) != 0) - width = atoi(com_argv[i+1]); - if ((i = COM_CheckParm("-height")) != 0) - height = atoi(com_argv[i+1]); - - if ((i = COM_CheckParm("-conwidth")) != 0) - vid.conwidth = Q_atoi(com_argv[i+1]); - else - vid.conwidth = 640; - - vid.conwidth &= 0xfff8; // make it a multiple of eight - - if (vid.conwidth < 320) - vid.conwidth = 320; - - // pick a conheight that matches with correct aspect - vid.conheight = vid.conwidth*3 / 4; - - if ((i = COM_CheckParm("-conheight")) != 0) - vid.conheight = Q_atoi(com_argv[i+1]); - if (vid.conheight < 200) - vid.conheight = 200; - - fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz, - attribs); - if (!fc) - Sys_Error("Unable to create 3DFX context.\n"); - - InitSig(); // trap evil signals - - scr_width = width; - scr_height = height; - - fxMesaMakeCurrent(fc); - - if (vid.conheight > height) - vid.conheight = height; - if (vid.conwidth > width) - vid.conwidth = width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - vid.numpages = 2; - - GL_Init(); - - sprintf (gldir, "%s/glquake", com_gamedir); - Sys_mkdir (gldir); - - Check_Gamma(palette); - VID_SetPalette(palette); - - // Check for 3DFX Extensions and initialize them. - VID_Init8bitPalette(); - - Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); - - vid.recalc_refdef = 1; // force a surface cache flush -} - -void Sys_SendKeyEvents(void) -{ - if (UseKeyboard) - while (keyboard_update()); -} - -void Force_CenterView_f (void) -{ - cl.viewangles[PITCH] = 0; -} - - -void mousehandler(int buttonstate, int dx, int dy) -{ - mouse_buttonstate = buttonstate; - mx += dx; - my += dy; -} - -void IN_Init(void) -{ - - int mtype; - char *mousedev; - int mouserate; - - if (UseMouse) - { - - Cvar_RegisterVariable (&mouse_button_commands[0]); - Cvar_RegisterVariable (&mouse_button_commands[1]); - Cvar_RegisterVariable (&mouse_button_commands[2]); - Cmd_AddCommand ("force_centerview", Force_CenterView_f); - - mouse_buttons = 3; - - mtype = vga_getmousetype(); - - mousedev = "/dev/mouse"; - if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV"); - if (COM_CheckParm("-mdev")) - mousedev = com_argv[COM_CheckParm("-mdev")+1]; - - mouserate = 1200; - if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE")); - if (COM_CheckParm("-mrate")) - mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]); - - if (mouse_init(mousedev, mtype, mouserate)) - { - Con_Printf("No mouse found\n"); - UseMouse = 0; - } - else - mouse_seteventhandler(mousehandler); - - } - -} - -void IN_Shutdown(void) -{ - if (UseMouse) - mouse_close(); -} - -/* -=========== -IN_Commands -=========== -*/ -void IN_Commands (void) -{ - if (UseMouse && cls.state != ca_dedicated) - { - // poll mouse values - while (mouse_update()) - ; - - // perform button actions - if ((mouse_buttonstate & MOUSE_LEFTBUTTON) && - !(mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) - Key_Event (K_MOUSE1, true); - else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) && - (mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) - Key_Event (K_MOUSE1, false); - - if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) && - !(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) - Key_Event (K_MOUSE2, true); - else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) && - (mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) - Key_Event (K_MOUSE2, false); - - if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) && - !(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) - Key_Event (K_MOUSE3, true); - else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) && - (mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) - Key_Event (K_MOUSE3, false); - - mouse_oldbuttonstate = mouse_buttonstate; - } -} - -/* -=========== -IN_Move -=========== -*/ -void IN_MouseMove (usercmd_t *cmd) -{ - if (!UseMouse) - return; - - // poll mouse values - while (mouse_update()) - ; - - if (m_filter.value) - { - mouse_x = (mx + old_mouse_x) * 0.5; - mouse_y = (my + old_mouse_y) * 0.5; - } - else - { - mouse_x = mx; - mouse_y = my; - } - old_mouse_x = mx; - old_mouse_y = my; - mx = my = 0; // clear for next update - - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; - -// add mouse X/Y movement to cmd - if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) - cmd->sidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) - { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } - else - { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } -} - -void IN_Move (usercmd_t *cmd) -{ - IN_MouseMove(cmd); -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*#include "vga.h" */ +#include "vgakeyboard.h" +#include "vgamouse.h" + +#include "quakedef.h" +#include "GL/fxmesa.h" + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +static fxMesaContext fc = NULL; +#define stringify(m) { #m, m } + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; +unsigned char d_15to8table[65536]; + +int num_shades=32; + +struct +{ + char *name; + int num; +} mice[] = +{ + stringify(MOUSE_MICROSOFT), + stringify(MOUSE_MOUSESYSTEMS), + stringify(MOUSE_MMSERIES), + stringify(MOUSE_LOGITECH), + stringify(MOUSE_BUSMOUSE), + stringify(MOUSE_PS2), +}; + +static unsigned char scantokey[128]; + +int num_mice = sizeof (mice) / sizeof(mice[0]); + +int d_con_indirect = 0; + +int svgalib_inited=0; +int UseMouse = 1; +int UseKeyboard = 1; + +int mouserate = MOUSE_DEFAULTSAMPLERATE; + +cvar_t vid_mode = {"vid_mode","5",false}; +cvar_t vid_redrawfull = {"vid_redrawfull","0",false}; +cvar_t vid_waitforrefresh = {"vid_waitforrefresh","0",true}; + +char *framebuffer_ptr; + +cvar_t mouse_button_commands[3] = +{ + {"mouse1","+attack"}, + {"mouse2","+strafe"}, + {"mouse3","+forward"}, +}; + +int mouse_buttons; +int mouse_buttonstate; +int mouse_oldbuttonstate; +float mouse_x, mouse_y; +float old_mouse_x, old_mouse_y; +int mx, my; + +cvar_t m_filter = {"m_filter","1"}; + +int scr_width, scr_height; + +/*-----------------------------------------------------------------------*/ + +//int texture_mode = GL_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; +int texture_mode = GL_LINEAR; +//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; +//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; + +int texture_extension_number = 1; + +float gldepthmin, gldepthmax; + +cvar_t gl_ztrick = {"gl_ztrick","1"}; + +const char *gl_vendor; +const char *gl_renderer; +const char *gl_version; +const char *gl_extensions; + +void (*qgl3DfxSetPaletteEXT) (GLuint *); +void (*qglColorTableEXT) (int, int, int, int, int, const void *); + +static float vid_gamma = 1.0; + +qboolean is8bit = false; +qboolean isPermedia = false; +qboolean gl_mtexable = false; + +/*-----------------------------------------------------------------------*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + +void D_EndDirectRect (int x, int y, int width, int height) +{ +} + +int matchmouse(int mouse, char *name) +{ + int i; + for (i=0 ; i> 2)+4; + b = ((i & 0x7C00) >> 7)+4; + pal = (unsigned char *)d_8to24table; + for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) { + r1 = (int)r - (int)pal[0]; + g1 = (int)g - (int)pal[1]; + b1 = (int)b - (int)pal[2]; + dist = (r1*r1)+(g1*g1)+(b1*b1); + if (dist < bestdist) { + k=v; + bestdist = dist; + } + } + d_15to8table[i]=k; + } +} + +void CheckMultiTextureExtensions(void) +{ + void *prjobj; + + if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { + Con_Printf("Found GL_SGIS_multitexture...\n"); + + if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { + Con_Printf("Unable to open symbol list for main program.\n"); + return; + } + + qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS"); + qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS"); + + if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) { + Con_Printf("Multitexture extensions found.\n"); + gl_mtexable = true; + } else + Con_Printf("Symbol not found, disabled.\n"); + + dlclose(prjobj); + } +} + +/* +=============== +GL_Init +=============== +*/ +void GL_Init (void) +{ + gl_vendor = glGetString (GL_VENDOR); + Con_Printf ("GL_VENDOR: %s\n", gl_vendor); + gl_renderer = glGetString (GL_RENDERER); + Con_Printf ("GL_RENDERER: %s\n", gl_renderer); + + gl_version = glGetString (GL_VERSION); + Con_Printf ("GL_VERSION: %s\n", gl_version); + gl_extensions = glGetString (GL_EXTENSIONS); + //Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); + Con_Printf ("The printing of the GL_EXTENSIONS string was causing a buffer overflow since the string is so huge. Not going to print, but kind of fixed it."); +// Con_Printf ("%s %s\n", gl_renderer, gl_version); + + CheckMultiTextureExtensions (); + + glClearColor (1,0,0,0); + glCullFace(GL_FRONT); + glEnable(GL_TEXTURE_2D); + + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.666); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glShadeModel (GL_FLAT); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +} + +/* +================= +GL_BeginRendering + +================= +*/ +void GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + extern cvar_t gl_clear; + + *x = *y = 0; + *width = scr_width; + *height = scr_height; + +// if (!wglMakeCurrent( maindc, baseRC )) +// Sys_Error ("wglMakeCurrent failed"); + +// glViewport (*x, *y, *width, *height); +} + + +void GL_EndRendering (void) +{ + glFlush(); + fxMesaSwapBuffers(); +} + +void Init_KBD(void) +{ + int i; + + if (COM_CheckParm("-nokbd")) UseKeyboard = 0; + + if (UseKeyboard) + { + for (i=0 ; i<128 ; i++) + scantokey[i] = ' '; + + scantokey[42] = K_SHIFT; + scantokey[54] = K_SHIFT; + scantokey[72] = K_UPARROW; + scantokey[103] = K_UPARROW; + scantokey[80] = K_DOWNARROW; + scantokey[108] = K_DOWNARROW; + scantokey[75] = K_LEFTARROW; + scantokey[105] = K_LEFTARROW; + scantokey[77] = K_RIGHTARROW; + scantokey[106] = K_RIGHTARROW; + scantokey[29] = K_CTRL; + scantokey[97] = K_CTRL; + scantokey[56] = K_ALT; + scantokey[100] = K_ALT; +// scantokey[58] = JK_CAPS; +// scantokey[69] = JK_NUM_LOCK; + scantokey[71] = K_HOME; + scantokey[73] = K_PGUP; + scantokey[79] = K_END; + scantokey[81] = K_PGDN; + scantokey[82] = K_INS; + scantokey[83] = K_DEL; + scantokey[1 ] = K_ESCAPE; + scantokey[28] = K_ENTER; + scantokey[15] = K_TAB; + scantokey[14] = K_BACKSPACE; + scantokey[119] = K_PAUSE; + scantokey[57] = ' '; + + scantokey[102] = K_HOME; + scantokey[104] = K_PGUP; + scantokey[107] = K_END; + scantokey[109] = K_PGDN; + scantokey[110] = K_INS; + scantokey[111] = K_DEL; + + scantokey[2] = '1'; + scantokey[3] = '2'; + scantokey[4] = '3'; + scantokey[5] = '4'; + scantokey[6] = '5'; + scantokey[7] = '6'; + scantokey[8] = '7'; + scantokey[9] = '8'; + scantokey[10] = '9'; + scantokey[11] = '0'; + scantokey[12] = '-'; + scantokey[13] = '='; + scantokey[41] = '`'; + scantokey[26] = '['; + scantokey[27] = ']'; + scantokey[39] = ';'; + scantokey[40] = '\''; + scantokey[51] = ','; + scantokey[52] = '.'; + scantokey[53] = '/'; + scantokey[43] = '\\'; + + scantokey[59] = K_F1; + scantokey[60] = K_F2; + scantokey[61] = K_F3; + scantokey[62] = K_F4; + scantokey[63] = K_F5; + scantokey[64] = K_F6; + scantokey[65] = K_F7; + scantokey[66] = K_F8; + scantokey[67] = K_F9; + scantokey[68] = K_F10; + scantokey[87] = K_F11; + scantokey[88] = K_F12; + scantokey[30] = 'a'; + scantokey[48] = 'b'; + scantokey[46] = 'c'; + scantokey[32] = 'd'; + scantokey[18] = 'e'; + scantokey[33] = 'f'; + scantokey[34] = 'g'; + scantokey[35] = 'h'; + scantokey[23] = 'i'; + scantokey[36] = 'j'; + scantokey[37] = 'k'; + scantokey[38] = 'l'; + scantokey[50] = 'm'; + scantokey[49] = 'n'; + scantokey[24] = 'o'; + scantokey[25] = 'p'; + scantokey[16] = 'q'; + scantokey[19] = 'r'; + scantokey[31] = 's'; + scantokey[20] = 't'; + scantokey[22] = 'u'; + scantokey[47] = 'v'; + scantokey[17] = 'w'; + scantokey[45] = 'x'; + scantokey[21] = 'y'; + scantokey[44] = 'z'; + + scantokey[78] = '+'; + scantokey[74] = '-'; + + if (keyboard_init()) + Sys_Error("keyboard_init() failed"); + keyboard_seteventhandler(keyhandler); + } +} + +#define NUM_RESOLUTIONS 16 + +static int resolutions[NUM_RESOLUTIONS][3]={ + 320,200, GR_RESOLUTION_320x200, + 320,240, GR_RESOLUTION_320x240, + 400,256, GR_RESOLUTION_400x256, + 400,300, GR_RESOLUTION_400x300, + 512,384, GR_RESOLUTION_512x384, + 640,200, GR_RESOLUTION_640x200, + 640,350, GR_RESOLUTION_640x350, + 640,400, GR_RESOLUTION_640x400, + 640,480, GR_RESOLUTION_640x480, + 800,600, GR_RESOLUTION_800x600, + 960,720, GR_RESOLUTION_960x720, + 856,480, GR_RESOLUTION_856x480, + 512,256, GR_RESOLUTION_512x256, + 1024,768, GR_RESOLUTION_1024x768, + 1280,1024,GR_RESOLUTION_1280x1024, + 1600,1200,GR_RESOLUTION_1600x1200 +}; + +int findres(int *width, int *height) +{ + int i; + + for(i=0;i 255) + inf = 255; + palette[i] = inf; + } + + memcpy (pal, palette, sizeof(palette)); +} + +void VID_Init(unsigned char *palette) +{ + int i; + GLint attribs[32]; + char gldir[MAX_OSPATH]; + int width = 640, height = 480; + + Init_KBD(); + + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&vid_redrawfull); + Cvar_RegisterVariable (&vid_waitforrefresh); + Cvar_RegisterVariable (&gl_ztrick); + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + +// interpret command-line params + +// set vid parameters + attribs[0] = FXMESA_DOUBLEBUFFER; + attribs[1] = FXMESA_ALPHA_SIZE; + attribs[2] = 1; + attribs[3] = FXMESA_DEPTH_SIZE; + attribs[4] = 1; + attribs[5] = FXMESA_NONE; + + if ((i = COM_CheckParm("-width")) != 0) + width = atoi(com_argv[i+1]); + if ((i = COM_CheckParm("-height")) != 0) + height = atoi(com_argv[i+1]); + + if ((i = COM_CheckParm("-conwidth")) != 0) + vid.conwidth = Q_atoi(com_argv[i+1]); + else + vid.conwidth = 640; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + + if (vid.conwidth < 320) + vid.conwidth = 320; + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth*3 / 4; + + if ((i = COM_CheckParm("-conheight")) != 0) + vid.conheight = Q_atoi(com_argv[i+1]); + if (vid.conheight < 200) + vid.conheight = 200; + + fc = fxMesaCreateContext(0, findres(&width, &height), GR_REFRESH_75Hz, + attribs); + if (!fc) + Sys_Error("Unable to create 3DFX context.\n"); + + InitSig(); // trap evil signals + + scr_width = width; + scr_height = height; + + fxMesaMakeCurrent(fc); + + if (vid.conheight > height) + vid.conheight = height; + if (vid.conwidth > width) + vid.conwidth = width; + vid.width = vid.conwidth; + vid.height = vid.conheight; + + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + vid.numpages = 2; + + GL_Init(); + + sprintf (gldir, "%s/glquake", com_gamedir); + Sys_mkdir (gldir); + + Check_Gamma(palette); + VID_SetPalette(palette); + + // Check for 3DFX Extensions and initialize them. + VID_Init8bitPalette(); + + Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); + + vid.recalc_refdef = 1; // force a surface cache flush +} + +void Sys_SendKeyEvents(void) +{ + if (UseKeyboard) + while (keyboard_update()); +} + +void Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + + +void mousehandler(int buttonstate, int dx, int dy) +{ + mouse_buttonstate = buttonstate; + mx += dx; + my += dy; +} + +void IN_Init(void) +{ + + int mtype; + char *mousedev; + int mouserate; + + if (UseMouse) + { + + Cvar_RegisterVariable (&mouse_button_commands[0]); + Cvar_RegisterVariable (&mouse_button_commands[1]); + Cvar_RegisterVariable (&mouse_button_commands[2]); + Cmd_AddCommand ("force_centerview", Force_CenterView_f); + + mouse_buttons = 3; + + mtype = vga_getmousetype(); + + mousedev = "/dev/mouse"; + if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV"); + if (COM_CheckParm("-mdev")) + mousedev = com_argv[COM_CheckParm("-mdev")+1]; + + mouserate = 1200; + if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE")); + if (COM_CheckParm("-mrate")) + mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]); + + if (mouse_init(mousedev, mtype, mouserate)) + { + Con_Printf("No mouse found\n"); + UseMouse = 0; + } + else + mouse_seteventhandler(mousehandler); + + } + +} + +void IN_Shutdown(void) +{ + if (UseMouse) + mouse_close(); +} + +/* +=========== +IN_Commands +=========== +*/ +void IN_Commands (void) +{ + if (UseMouse && cls.state != ca_dedicated) + { + // poll mouse values + while (mouse_update()) + ; + + // perform button actions + if ((mouse_buttonstate & MOUSE_LEFTBUTTON) && + !(mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) + Key_Event (K_MOUSE1, true); + else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) && + (mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) + Key_Event (K_MOUSE1, false); + + if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) && + !(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) + Key_Event (K_MOUSE2, true); + else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) && + (mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) + Key_Event (K_MOUSE2, false); + + if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) && + !(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) + Key_Event (K_MOUSE3, true); + else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) && + (mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) + Key_Event (K_MOUSE3, false); + + mouse_oldbuttonstate = mouse_buttonstate; + } +} + +/* +=========== +IN_Move +=========== +*/ +void IN_MouseMove (usercmd_t *cmd) +{ + if (!UseMouse) + return; + + // poll mouse values + while (mouse_update()) + ; + + if (m_filter.value) + { + mouse_x = (mx + old_mouse_x) * 0.5; + mouse_y = (my + old_mouse_y) * 0.5; + } + else + { + mouse_x = mx; + mouse_y = my; + } + old_mouse_x = mx; + old_mouse_y = my; + mx = my = 0; // clear for next update + + mouse_x *= sensitivity.value; + mouse_y *= sensitivity.value; + +// add mouse X/Y movement to cmd + if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) + cmd->sidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } +} + +void IN_Move (usercmd_t *cmd) +{ + IN_MouseMove(cmd); +} + + diff --git a/WinQuake/gl_vidlinuxglx.c b/WinQuake/gl_vidlinuxglx.c index 400adb4..ac242f3 100644 --- a/WinQuake/gl_vidlinuxglx.c +++ b/WinQuake/gl_vidlinuxglx.c @@ -1,997 +1,998 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "quakedef.h" - -#include - -#include -#include - -#include -#include - -#define WARP_WIDTH 320 -#define WARP_HEIGHT 200 - -static Display *dpy = NULL; -static int scrnum; -static Window win; -static GLXContext ctx = NULL; - -#define KEY_MASK (KeyPressMask | KeyReleaseMask) -#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \ - PointerMotionMask | ButtonMotionMask ) -#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask ) - - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; -unsigned char d_15to8table[65536]; - -cvar_t vid_mode = {"vid_mode","0",false}; - -static qboolean mouse_avail; -static qboolean mouse_active; -static int mx, my; -static int old_mouse_x, old_mouse_y; - -static cvar_t in_mouse = {"in_mouse", "1", false}; -static cvar_t in_dgamouse = {"in_dgamouse", "1", false}; -static cvar_t m_filter = {"m_filter", "0"}; - -qboolean dgamouse = false; -qboolean vidmode_ext = false; - -static int win_x, win_y; - -static int scr_width, scr_height; - -static XF86VidModeModeInfo **vidmodes; -static int default_dotclock_vidmode; -static int num_vidmodes; -static qboolean vidmode_active = false; - -/*-----------------------------------------------------------------------*/ - -//int texture_mode = GL_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; -//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; -int texture_mode = GL_LINEAR; -//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; -//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; - -int texture_extension_number = 1; - -float gldepthmin, gldepthmax; - -cvar_t gl_ztrick = {"gl_ztrick","1"}; - -const char *gl_vendor; -const char *gl_renderer; -const char *gl_version; -const char *gl_extensions; - -void (*qglColorTableEXT) (int, int, int, int, int, const void*); -void (*qgl3DfxSetPaletteEXT) (GLuint *); - -static float vid_gamma = 1.0; - -qboolean is8bit = false; -qboolean isPermedia = false; -qboolean gl_mtexable = false; - -/*-----------------------------------------------------------------------*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ -} - -void D_EndDirectRect (int x, int y, int width, int height) -{ -} - -static int XLateKey(XKeyEvent *ev) -{ - - int key; - char buf[64]; - KeySym keysym; - - key = 0; - - XLookupString(ev, buf, sizeof buf, &keysym, 0); - - switch(keysym) - { - case XK_KP_Page_Up: - case XK_Page_Up: key = K_PGUP; break; - - case XK_KP_Page_Down: - case XK_Page_Down: key = K_PGDN; break; - - case XK_KP_Home: - case XK_Home: key = K_HOME; break; - - case XK_KP_End: - case XK_End: key = K_END; break; - - case XK_KP_Left: - case XK_Left: key = K_LEFTARROW; break; - - case XK_KP_Right: - case XK_Right: key = K_RIGHTARROW; break; - - case XK_KP_Down: - case XK_Down: key = K_DOWNARROW; break; - - case XK_KP_Up: - case XK_Up: key = K_UPARROW; break; - - case XK_Escape: key = K_ESCAPE; break; - - case XK_KP_Enter: - case XK_Return: key = K_ENTER; break; - - case XK_Tab: key = K_TAB; break; - - case XK_F1: key = K_F1; break; - - case XK_F2: key = K_F2; break; - - case XK_F3: key = K_F3; break; - - case XK_F4: key = K_F4; break; - - case XK_F5: key = K_F5; break; - - case XK_F6: key = K_F6; break; - - case XK_F7: key = K_F7; break; - - case XK_F8: key = K_F8; break; - - case XK_F9: key = K_F9; break; - - case XK_F10: key = K_F10; break; - - case XK_F11: key = K_F11; break; - - case XK_F12: key = K_F12; break; - - case XK_BackSpace: key = K_BACKSPACE; break; - - case XK_KP_Delete: - case XK_Delete: key = K_DEL; break; - - case XK_Pause: key = K_PAUSE; break; - - case XK_Shift_L: - case XK_Shift_R: key = K_SHIFT; break; - - case XK_Execute: - case XK_Control_L: - case XK_Control_R: key = K_CTRL; break; - - case XK_Alt_L: - case XK_Meta_L: - case XK_Alt_R: - case XK_Meta_R: key = K_ALT; break; - - case XK_KP_Begin: key = '5'; break; - - case XK_KP_Insert: - case XK_Insert:key = K_INS; break; - - case XK_KP_Multiply: key = '*'; break; - case XK_KP_Add: key = '+'; break; - case XK_KP_Subtract: key = '-'; break; - case XK_KP_Divide: key = '/'; break; - -#if 0 - case 0x021: key = '1';break;/* [!] */ - case 0x040: key = '2';break;/* [@] */ - case 0x023: key = '3';break;/* [#] */ - case 0x024: key = '4';break;/* [$] */ - case 0x025: key = '5';break;/* [%] */ - case 0x05e: key = '6';break;/* [^] */ - case 0x026: key = '7';break;/* [&] */ - case 0x02a: key = '8';break;/* [*] */ - case 0x028: key = '9';;break;/* [(] */ - case 0x029: key = '0';break;/* [)] */ - case 0x05f: key = '-';break;/* [_] */ - case 0x02b: key = '=';break;/* [+] */ - case 0x07c: key = '\'';break;/* [|] */ - case 0x07d: key = '[';break;/* [}] */ - case 0x07b: key = ']';break;/* [{] */ - case 0x022: key = '\'';break;/* ["] */ - case 0x03a: key = ';';break;/* [:] */ - case 0x03f: key = '/';break;/* [?] */ - case 0x03e: key = '.';break;/* [>] */ - case 0x03c: key = ',';break;/* [<] */ -#endif - - default: - key = *(unsigned char*)buf; - if (key >= 'A' && key <= 'Z') - key = key - 'A' + 'a'; - break; - } - - return key; -} - -static Cursor CreateNullCursor(Display *display, Window root) -{ - Pixmap cursormask; - XGCValues xgc; - GC gc; - XColor dummycolour; - Cursor cursor; - - cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); - xgc.function = GXclear; - gc = XCreateGC(display, cursormask, GCFunction, &xgc); - XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); - dummycolour.pixel = 0; - dummycolour.red = 0; - dummycolour.flags = 04; - cursor = XCreatePixmapCursor(display, cursormask, cursormask, - &dummycolour,&dummycolour, 0,0); - XFreePixmap(display,cursormask); - XFreeGC(display,gc); - return cursor; -} - -static void install_grabs(void) -{ - -// inviso cursor - XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); - - XGrabPointer(dpy, win, - True, - 0, - GrabModeAsync, GrabModeAsync, - win, - None, - CurrentTime); - - if (in_dgamouse.value) { - int MajorVersion, MinorVersion; - - if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { - // unable to query, probalby not supported - Con_Printf( "Failed to detect XF86DGA Mouse\n" ); - in_dgamouse.value = 0; - } else { - dgamouse = true; - XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); - XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); - } - } else { - XWarpPointer(dpy, None, win, - 0, 0, 0, 0, - vid.width / 2, vid.height / 2); - } - - XGrabKeyboard(dpy, win, - False, - GrabModeAsync, GrabModeAsync, - CurrentTime); - - mouse_active = true; - -// XSync(dpy, True); -} - -static void uninstall_grabs(void) -{ - if (!dpy || !win) - return; - - if (dgamouse) { - dgamouse = false; - XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); - } - - XUngrabPointer(dpy, CurrentTime); - XUngrabKeyboard(dpy, CurrentTime); - -// inviso cursor - XUndefineCursor(dpy, win); - - mouse_active = false; -} - -static void HandleEvents(void) -{ - XEvent event; - KeySym ks; - int b; - qboolean dowarp = false; - int mwx = vid.width/2; - int mwy = vid.height/2; - - if (!dpy) - return; - - while (XPending(dpy)) { - XNextEvent(dpy, &event); - - switch (event.type) { - case KeyPress: - case KeyRelease: - Key_Event(XLateKey(&event.xkey), event.type == KeyPress); - break; - - case MotionNotify: - if (mouse_active) { - if (dgamouse) { - mx += (event.xmotion.x + win_x) * 2; - my += (event.xmotion.y + win_y) * 2; - } - else - { - mx += ((int)event.xmotion.x - mwx) * 2; - my += ((int)event.xmotion.y - mwy) * 2; - mwx = event.xmotion.x; - mwy = event.xmotion.y; - - if (mx || my) - dowarp = true; - } - } - break; - - break; - - case ButtonPress: - b=-1; - if (event.xbutton.button == 1) - b = 0; - else if (event.xbutton.button == 2) - b = 2; - else if (event.xbutton.button == 3) - b = 1; - if (b>=0) - Key_Event(K_MOUSE1 + b, true); - break; - - case ButtonRelease: - b=-1; - if (event.xbutton.button == 1) - b = 0; - else if (event.xbutton.button == 2) - b = 2; - else if (event.xbutton.button == 3) - b = 1; - if (b>=0) - Key_Event(K_MOUSE1 + b, false); - break; - - case CreateNotify : - win_x = event.xcreatewindow.x; - win_y = event.xcreatewindow.y; - break; - - case ConfigureNotify : - win_x = event.xconfigure.x; - win_y = event.xconfigure.y; - break; - } - } - - if (dowarp) { - /* move the mouse to the window center again */ - XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); - } - -} - -static void IN_DeactivateMouse( void ) -{ - if (!mouse_avail || !dpy || !win) - return; - - if (mouse_active) { - uninstall_grabs(); - mouse_active = false; - } -} - -static void IN_ActivateMouse( void ) -{ - if (!mouse_avail || !dpy || !win) - return; - - if (!mouse_active) { - mx = my = 0; // don't spazz - install_grabs(); - mouse_active = true; - } -} - - -void VID_Shutdown(void) -{ - if (!ctx || !dpy) - return; - IN_DeactivateMouse(); - if (dpy) { - if (ctx) - glXDestroyContext(dpy, ctx); - if (win) - XDestroyWindow(dpy, win); - if (vidmode_active) - XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]); - XCloseDisplay(dpy); - } - vidmode_active = false; - dpy = NULL; - win = 0; - ctx = NULL; -} - -void signal_handler(int sig) -{ - printf("Received signal %d, exiting...\n", sig); - Sys_Quit(); - exit(0); -} - -void InitSig(void) -{ - signal(SIGHUP, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGQUIT, signal_handler); - signal(SIGILL, signal_handler); - signal(SIGTRAP, signal_handler); - signal(SIGIOT, signal_handler); - signal(SIGBUS, signal_handler); - signal(SIGFPE, signal_handler); - signal(SIGSEGV, signal_handler); - signal(SIGTERM, signal_handler); -} - -void VID_ShiftPalette(unsigned char *p) -{ -// VID_SetPalette(p); -} - -void VID_SetPalette (unsigned char *palette) -{ - byte *pal; - unsigned r,g,b; - unsigned v; - int r1,g1,b1; - int j,k,l,m; - unsigned short i; - unsigned *table; - FILE *f; - char s[255]; - int dist, bestdist; - -// -// 8 8 8 encoding -// - pal = palette; - table = d_8to24table; - for (i=0 ; i<256 ; i++) - { - r = pal[0]; - g = pal[1]; - b = pal[2]; - pal += 3; - - v = (255<<24) + (r<<0) + (g<<8) + (b<<16); - *table++ = v; - } - d_8to24table[255] &= 0xffffff; // 255 is transparent - - for (i=0; i < (1<<15); i++) { - /* Maps - 000000000000000 - 000000000011111 = Red = 0x1F - 000001111100000 = Blue = 0x03E0 - 111110000000000 = Grn = 0x7C00 - */ - r = ((i & 0x1F) << 3)+4; - g = ((i & 0x03E0) >> 2)+4; - b = ((i & 0x7C00) >> 7)+4; - pal = (unsigned char *)d_8to24table; - for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) { - r1 = (int)r - (int)pal[0]; - g1 = (int)g - (int)pal[1]; - b1 = (int)b - (int)pal[2]; - dist = (r1*r1)+(g1*g1)+(b1*b1); - if (dist < bestdist) { - k=v; - bestdist = dist; - } - } - d_15to8table[i]=k; - } -} - -void CheckMultiTextureExtensions(void) -{ - void *prjobj; - - if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { - Con_Printf("Found GL_SGIS_multitexture...\n"); - - if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { - Con_Printf("Unable to open symbol list for main program.\n"); - return; - } - - qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS"); - qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS"); - - if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) { - Con_Printf("Multitexture extensions found.\n"); - gl_mtexable = true; - } else - Con_Printf("Symbol not found, disabled.\n"); - - dlclose(prjobj); - } -} - -/* -=============== -GL_Init -=============== -*/ -void GL_Init (void) -{ - gl_vendor = glGetString (GL_VENDOR); - Con_Printf ("GL_VENDOR: %s\n", gl_vendor); - gl_renderer = glGetString (GL_RENDERER); - Con_Printf ("GL_RENDERER: %s\n", gl_renderer); - - gl_version = glGetString (GL_VERSION); - Con_Printf ("GL_VERSION: %s\n", gl_version); - gl_extensions = glGetString (GL_EXTENSIONS); - Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); - -// Con_Printf ("%s %s\n", gl_renderer, gl_version); - - CheckMultiTextureExtensions (); - - glClearColor (1,0,0,0); - glCullFace(GL_FRONT); - glEnable(GL_TEXTURE_2D); - - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.666); - - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glShadeModel (GL_FLAT); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -} - -/* -================= -GL_BeginRendering - -================= -*/ -void GL_BeginRendering (int *x, int *y, int *width, int *height) -{ - extern cvar_t gl_clear; - - *x = *y = 0; - *width = scr_width; - *height = scr_height; - -// if (!wglMakeCurrent( maindc, baseRC )) -// Sys_Error ("wglMakeCurrent failed"); - -// glViewport (*x, *y, *width, *height); -} - - -void GL_EndRendering (void) -{ - glFlush(); - glXSwapBuffers(dpy, win); -} - -qboolean VID_Is8bit(void) -{ - return is8bit; -} - -void VID_Init8bitPalette(void) -{ - // Check for 8bit Extensions and initialize them. - int i; - void *prjobj; - - if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { - Con_Printf("Unable to open symbol list for main program.\n"); - return; - } - - if (strstr(gl_extensions, "3DFX_set_global_palette") && - (qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) { - GLubyte table[256][4]; - char *oldpal; - - Con_SafePrintf("8-bit GL extensions enabled.\n"); - glEnable( GL_SHARED_TEXTURE_PALETTE_EXT ); - oldpal = (char *) d_8to24table; //d_8to24table3dfx; - for (i=0;i<256;i++) { - table[i][2] = *oldpal++; - table[i][1] = *oldpal++; - table[i][0] = *oldpal++; - table[i][3] = 255; - oldpal++; - } - qgl3DfxSetPaletteEXT((GLuint *)table); - is8bit = true; - - } else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") && - (qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) { - char thePalette[256*3]; - char *oldPalette, *newPalette; - - Con_SafePrintf("8-bit GL extensions enabled.\n"); - glEnable( GL_SHARED_TEXTURE_PALETTE_EXT ); - oldPalette = (char *) d_8to24table; //d_8to24table3dfx; - newPalette = thePalette; - for (i=0;i<256;i++) { - *newPalette++ = *oldPalette++; - *newPalette++ = *oldPalette++; - *newPalette++ = *oldPalette++; - oldPalette++; - } - qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette); - is8bit = true; - } - - dlclose(prjobj); -} - -static void Check_Gamma (unsigned char *pal) -{ - float f, inf; - unsigned char palette[768]; - int i; - - if ((i = COM_CheckParm("-gamma")) == 0) { - if ((gl_renderer && strstr(gl_renderer, "Voodoo")) || - (gl_vendor && strstr(gl_vendor, "3Dfx"))) - vid_gamma = 1; - else - vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware - } else - vid_gamma = Q_atof(com_argv[i+1]); - - for (i=0 ; i<768 ; i++) - { - f = pow ( (pal[i]+1)/256.0 , vid_gamma ); - inf = f*255 + 0.5; - if (inf < 0) - inf = 0; - if (inf > 255) - inf = 255; - palette[i] = inf; - } - - memcpy (pal, palette, sizeof(palette)); -} - -void VID_Init(unsigned char *palette) -{ - int i; - int attrib[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - None - }; - char gldir[MAX_OSPATH]; - int width = 640, height = 480; - XSetWindowAttributes attr; - unsigned long mask; - Window root; - XVisualInfo *visinfo; - qboolean fullscreen = true; - int MajorVersion, MinorVersion; - int actualWidth, actualHeight; - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&in_mouse); - Cvar_RegisterVariable (&in_dgamouse); - Cvar_RegisterVariable (&m_filter); - Cvar_RegisterVariable (&gl_ztrick); - - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - -// interpret command-line params - -// set vid parameters - if ((i = COM_CheckParm("-window")) != 0) - fullscreen = false; - - if ((i = COM_CheckParm("-width")) != 0) - width = atoi(com_argv[i+1]); - - if ((i = COM_CheckParm("-height")) != 0) - height = atoi(com_argv[i+1]); - - if ((i = COM_CheckParm("-conwidth")) != 0) - vid.conwidth = Q_atoi(com_argv[i+1]); - else - vid.conwidth = 640; - - vid.conwidth &= 0xfff8; // make it a multiple of eight - - if (vid.conwidth < 320) - vid.conwidth = 320; - - // pick a conheight that matches with correct aspect - vid.conheight = vid.conwidth*3 / 4; - - if ((i = COM_CheckParm("-conheight")) != 0) - vid.conheight = Q_atoi(com_argv[i+1]); - if (vid.conheight < 200) - vid.conheight = 200; - - if (!(dpy = XOpenDisplay(NULL))) { - fprintf(stderr, "Error couldn't open the X display\n"); - exit(1); - } - - scrnum = DefaultScreen(dpy); - root = RootWindow(dpy, scrnum); - - // Get video mode list - MajorVersion = MinorVersion = 0; - if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { - vidmode_ext = false; - } else { - Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion); - vidmode_ext = true; - } - - visinfo = glXChooseVisual(dpy, scrnum, attrib); - if (!visinfo) { - fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n"); - exit(1); - } - - if (vidmode_ext) { - int best_fit, best_dist, dist, x, y; - - XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); - - // Are we going fullscreen? If so, let's change video mode - if (fullscreen) { - best_dist = 9999999; - best_fit = -1; - - for (i = 0; i < num_vidmodes; i++) { - if (width > vidmodes[i]->hdisplay || - height > vidmodes[i]->vdisplay) - continue; - - x = width - vidmodes[i]->hdisplay; - y = height - vidmodes[i]->vdisplay; - dist = (x * x) + (y * y); - if (dist < best_dist) { - best_dist = dist; - best_fit = i; - } - } - - if (best_fit != -1) { - actualWidth = vidmodes[best_fit]->hdisplay; - actualHeight = vidmodes[best_fit]->vdisplay; - - // change to the mode - XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]); - vidmode_active = true; - - // Move the viewport to top left - XF86VidModeSetViewPort(dpy, scrnum, 0, 0); - } else - fullscreen = 0; - } - } - - /* window attributes */ - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); - attr.event_mask = X_MASK; - if (vidmode_active) { - mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | - CWEventMask | CWOverrideRedirect; - attr.override_redirect = True; - attr.backing_store = NotUseful; - attr.save_under = False; - } else - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - win = XCreateWindow(dpy, root, 0, 0, width, height, - 0, visinfo->depth, InputOutput, - visinfo->visual, mask, &attr); - XMapWindow(dpy, win); - - if (vidmode_active) { - XMoveWindow(dpy, win, 0, 0); - XRaiseWindow(dpy, win); - XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); - XFlush(dpy); - // Move the viewport to top left - XF86VidModeSetViewPort(dpy, scrnum, 0, 0); - } - - XFlush(dpy); - - ctx = glXCreateContext(dpy, visinfo, NULL, True); - - glXMakeCurrent(dpy, win, ctx); - - scr_width = width; - scr_height = height; - - if (vid.conheight > height) - vid.conheight = height; - if (vid.conwidth > width) - vid.conwidth = width; - vid.width = vid.conwidth; - vid.height = vid.conheight; - - vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); - vid.numpages = 2; - - InitSig(); // trap evil signals - - GL_Init(); - - sprintf (gldir, "%s/glquake", com_gamedir); - Sys_mkdir (gldir); - - VID_SetPalette(palette); - - // Check for 3DFX Extensions and initialize them. - VID_Init8bitPalette(); - - Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); - - vid.recalc_refdef = 1; // force a surface cache flush -} - -void Sys_SendKeyEvents(void) -{ - HandleEvents(); -} - -void Force_CenterView_f (void) -{ - cl.viewangles[PITCH] = 0; -} - -void IN_Init(void) -{ -} - -void IN_Shutdown(void) -{ -} - -/* -=========== -IN_Commands -=========== -*/ -void IN_Commands (void) -{ - if (!dpy || !win) - return; - - if (vidmode_active || key_dest == key_game) - IN_ActivateMouse(); - else - IN_DeactivateMouse (); -} - -/* -=========== -IN_Move -=========== -*/ -void IN_MouseMove (usercmd_t *cmd) -{ - if (!mouse_avail) - return; - - if (m_filter.value) - { - mx = (mx + old_mouse_x) * 0.5; - my = (my + old_mouse_y) * 0.5; - } - old_mouse_x = mx; - old_mouse_y = my; - - mx *= sensitivity.value; - my *= sensitivity.value; - -// add mouse X/Y movement to cmd - if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) - cmd->sidemove += m_side.value * mx; - else - cl.viewangles[YAW] -= m_yaw.value * mx; - - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) - { - cl.viewangles[PITCH] += m_pitch.value * my; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } - else - { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * my; - else - cmd->forwardmove -= m_forward.value * my; - } - mx = my = 0; -} - -void IN_Move (usercmd_t *cmd) -{ - IN_MouseMove(cmd); -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "quakedef.h" + +#include + +#include +#include + +#include +#include + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 200 + +static Display *dpy = NULL; +static int scrnum; +static Window win; +static GLXContext ctx = NULL; + +#define KEY_MASK (KeyPressMask | KeyReleaseMask) +#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \ + PointerMotionMask | ButtonMotionMask ) +#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask ) + + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; +unsigned char d_15to8table[65536]; + +cvar_t vid_mode = {"vid_mode","0",false}; + +static qboolean mouse_avail; +static qboolean mouse_active; +static int mx, my; +static int old_mouse_x, old_mouse_y; + +static cvar_t in_mouse = {"in_mouse", "1", false}; +static cvar_t in_dgamouse = {"in_dgamouse", "1", false}; +static cvar_t m_filter = {"m_filter", "0"}; + +qboolean dgamouse = false; +qboolean vidmode_ext = false; + +static int win_x, win_y; + +static int scr_width, scr_height; + +static XF86VidModeModeInfo **vidmodes; +static int default_dotclock_vidmode; +static int num_vidmodes; +static qboolean vidmode_active = false; + +/*-----------------------------------------------------------------------*/ + +//int texture_mode = GL_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_NEAREST; +//int texture_mode = GL_NEAREST_MIPMAP_LINEAR; +int texture_mode = GL_LINEAR; +//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; +//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; + +int texture_extension_number = 1; + +float gldepthmin, gldepthmax; + +cvar_t gl_ztrick = {"gl_ztrick","1"}; + +const char *gl_vendor; +const char *gl_renderer; +const char *gl_version; +const char *gl_extensions; + +void (*qglColorTableEXT) (int, int, int, int, int, const void*); +void (*qgl3DfxSetPaletteEXT) (GLuint *); + +static float vid_gamma = 1.0; + +qboolean is8bit = false; +qboolean isPermedia = false; +qboolean gl_mtexable = false; + +/*-----------------------------------------------------------------------*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + +void D_EndDirectRect (int x, int y, int width, int height) +{ +} + +static int XLateKey(XKeyEvent *ev) +{ + + int key; + char buf[64]; + KeySym keysym; + + key = 0; + + XLookupString(ev, buf, sizeof buf, &keysym, 0); + + switch(keysym) + { + case XK_KP_Page_Up: + case XK_Page_Up: key = K_PGUP; break; + + case XK_KP_Page_Down: + case XK_Page_Down: key = K_PGDN; break; + + case XK_KP_Home: + case XK_Home: key = K_HOME; break; + + case XK_KP_End: + case XK_End: key = K_END; break; + + case XK_KP_Left: + case XK_Left: key = K_LEFTARROW; break; + + case XK_KP_Right: + case XK_Right: key = K_RIGHTARROW; break; + + case XK_KP_Down: + case XK_Down: key = K_DOWNARROW; break; + + case XK_KP_Up: + case XK_Up: key = K_UPARROW; break; + + case XK_Escape: key = K_ESCAPE; break; + + case XK_KP_Enter: + case XK_Return: key = K_ENTER; break; + + case XK_Tab: key = K_TAB; break; + + case XK_F1: key = K_F1; break; + + case XK_F2: key = K_F2; break; + + case XK_F3: key = K_F3; break; + + case XK_F4: key = K_F4; break; + + case XK_F5: key = K_F5; break; + + case XK_F6: key = K_F6; break; + + case XK_F7: key = K_F7; break; + + case XK_F8: key = K_F8; break; + + case XK_F9: key = K_F9; break; + + case XK_F10: key = K_F10; break; + + case XK_F11: key = K_F11; break; + + case XK_F12: key = K_F12; break; + + case XK_BackSpace: key = K_BACKSPACE; break; + + case XK_KP_Delete: + case XK_Delete: key = K_DEL; break; + + case XK_Pause: key = K_PAUSE; break; + + case XK_Shift_L: + case XK_Shift_R: key = K_SHIFT; break; + + case XK_Execute: + case XK_Control_L: + case XK_Control_R: key = K_CTRL; break; + + case XK_Alt_L: + case XK_Meta_L: + case XK_Alt_R: + case XK_Meta_R: key = K_ALT; break; + + case XK_KP_Begin: key = '5'; break; + + case XK_KP_Insert: + case XK_Insert:key = K_INS; break; + + case XK_KP_Multiply: key = '*'; break; + case XK_KP_Add: key = '+'; break; + case XK_KP_Subtract: key = '-'; break; + case XK_KP_Divide: key = '/'; break; + +#if 0 + case 0x021: key = '1';break;/* [!] */ + case 0x040: key = '2';break;/* [@] */ + case 0x023: key = '3';break;/* [#] */ + case 0x024: key = '4';break;/* [$] */ + case 0x025: key = '5';break;/* [%] */ + case 0x05e: key = '6';break;/* [^] */ + case 0x026: key = '7';break;/* [&] */ + case 0x02a: key = '8';break;/* [*] */ + case 0x028: key = '9';;break;/* [(] */ + case 0x029: key = '0';break;/* [)] */ + case 0x05f: key = '-';break;/* [_] */ + case 0x02b: key = '=';break;/* [+] */ + case 0x07c: key = '\'';break;/* [|] */ + case 0x07d: key = '[';break;/* [}] */ + case 0x07b: key = ']';break;/* [{] */ + case 0x022: key = '\'';break;/* ["] */ + case 0x03a: key = ';';break;/* [:] */ + case 0x03f: key = '/';break;/* [?] */ + case 0x03e: key = '.';break;/* [>] */ + case 0x03c: key = ',';break;/* [<] */ +#endif + + default: + key = *(unsigned char*)buf; + if (key >= 'A' && key <= 'Z') + key = key - 'A' + 'a'; + break; + } + + return key; +} + +static Cursor CreateNullCursor(Display *display, Window root) +{ + Pixmap cursormask; + XGCValues xgc; + GC gc; + XColor dummycolour; + Cursor cursor; + + cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); + xgc.function = GXclear; + gc = XCreateGC(display, cursormask, GCFunction, &xgc); + XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + cursor = XCreatePixmapCursor(display, cursormask, cursormask, + &dummycolour,&dummycolour, 0,0); + XFreePixmap(display,cursormask); + XFreeGC(display,gc); + return cursor; +} + +static void install_grabs(void) +{ + +// inviso cursor + XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); + + XGrabPointer(dpy, win, + True, + 0, + GrabModeAsync, GrabModeAsync, + win, + None, + CurrentTime); + + if (in_dgamouse.value) { + int MajorVersion, MinorVersion; + + if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { + // unable to query, probalby not supported + Con_Printf( "Failed to detect XF86DGA Mouse\n" ); + in_dgamouse.value = 0; + } else { + dgamouse = true; + XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); + XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); + } + } else { + XWarpPointer(dpy, None, win, + 0, 0, 0, 0, + vid.width / 2, vid.height / 2); + } + + XGrabKeyboard(dpy, win, + False, + GrabModeAsync, GrabModeAsync, + CurrentTime); + + mouse_active = true; + +// XSync(dpy, True); +} + +static void uninstall_grabs(void) +{ + if (!dpy || !win) + return; + + if (dgamouse) { + dgamouse = false; + XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); + } + + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + +// inviso cursor + XUndefineCursor(dpy, win); + + mouse_active = false; +} + +static void HandleEvents(void) +{ + XEvent event; + KeySym ks; + int b; + qboolean dowarp = false; + int mwx = vid.width/2; + int mwy = vid.height/2; + + if (!dpy) + return; + + while (XPending(dpy)) { + XNextEvent(dpy, &event); + + switch (event.type) { + case KeyPress: + case KeyRelease: + Key_Event(XLateKey(&event.xkey), event.type == KeyPress); + break; + + case MotionNotify: + if (mouse_active) { + if (dgamouse) { + mx += (event.xmotion.x + win_x) * 2; + my += (event.xmotion.y + win_y) * 2; + } + else + { + mx += ((int)event.xmotion.x - mwx) * 2; + my += ((int)event.xmotion.y - mwy) * 2; + mwx = event.xmotion.x; + mwy = event.xmotion.y; + + if (mx || my) + dowarp = true; + } + } + break; + + break; + + case ButtonPress: + b=-1; + if (event.xbutton.button == 1) + b = 0; + else if (event.xbutton.button == 2) + b = 2; + else if (event.xbutton.button == 3) + b = 1; + if (b>=0) + Key_Event(K_MOUSE1 + b, true); + break; + + case ButtonRelease: + b=-1; + if (event.xbutton.button == 1) + b = 0; + else if (event.xbutton.button == 2) + b = 2; + else if (event.xbutton.button == 3) + b = 1; + if (b>=0) + Key_Event(K_MOUSE1 + b, false); + break; + + case CreateNotify : + win_x = event.xcreatewindow.x; + win_y = event.xcreatewindow.y; + break; + + case ConfigureNotify : + win_x = event.xconfigure.x; + win_y = event.xconfigure.y; + break; + } + } + + if (dowarp) { + /* move the mouse to the window center again */ + XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); + } + +} + +static void IN_DeactivateMouse( void ) +{ + if (!mouse_avail || !dpy || !win) + return; + + if (mouse_active) { + uninstall_grabs(); + mouse_active = false; + } +} + +static void IN_ActivateMouse( void ) +{ + if (!mouse_avail || !dpy || !win) + return; + + if (!mouse_active) { + mx = my = 0; // don't spazz + install_grabs(); + mouse_active = true; + } +} + + +void VID_Shutdown(void) +{ + if (!ctx || !dpy) + return; + IN_DeactivateMouse(); + if (dpy) { + if (ctx) + glXDestroyContext(dpy, ctx); + if (win) + XDestroyWindow(dpy, win); + if (vidmode_active) + XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]); + XCloseDisplay(dpy); + } + vidmode_active = false; + dpy = NULL; + win = 0; + ctx = NULL; +} + +void signal_handler(int sig) +{ + printf("Received signal %d, exiting...\n", sig); + Sys_Quit(); + exit(0); +} + +void InitSig(void) +{ + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGQUIT, signal_handler); + signal(SIGILL, signal_handler); + signal(SIGTRAP, signal_handler); + signal(SIGIOT, signal_handler); + signal(SIGBUS, signal_handler); + signal(SIGFPE, signal_handler); + signal(SIGSEGV, signal_handler); + signal(SIGTERM, signal_handler); +} + +void VID_ShiftPalette(unsigned char *p) +{ +// VID_SetPalette(p); +} + +void VID_SetPalette (unsigned char *palette) +{ + byte *pal; + unsigned r,g,b; + unsigned v; + int r1,g1,b1; + int j,k,l,m; + unsigned short i; + unsigned *table; + FILE *f; + char s[255]; + int dist, bestdist; + +// +// 8 8 8 encoding +// + pal = palette; + table = d_8to24table; + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + v = (255<<24) + (r<<0) + (g<<8) + (b<<16); + *table++ = v; + } + d_8to24table[255] &= 0xffffff; // 255 is transparent + + for (i=0; i < (1<<15); i++) { + /* Maps + 000000000000000 + 000000000011111 = Red = 0x1F + 000001111100000 = Blue = 0x03E0 + 111110000000000 = Grn = 0x7C00 + */ + r = ((i & 0x1F) << 3)+4; + g = ((i & 0x03E0) >> 2)+4; + b = ((i & 0x7C00) >> 7)+4; + pal = (unsigned char *)d_8to24table; + for (v=0,k=0,bestdist=10000*10000; v<256; v++,pal+=4) { + r1 = (int)r - (int)pal[0]; + g1 = (int)g - (int)pal[1]; + b1 = (int)b - (int)pal[2]; + dist = (r1*r1)+(g1*g1)+(b1*b1); + if (dist < bestdist) { + k=v; + bestdist = dist; + } + } + d_15to8table[i]=k; + } +} + +void CheckMultiTextureExtensions(void) +{ + void *prjobj; + + if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) { + Con_Printf("Found GL_SGIS_multitexture...\n"); + + if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { + Con_Printf("Unable to open symbol list for main program.\n"); + return; + } + + qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS"); + qglSelectTextureSGIS = (void *) dlsym(prjobj, "glSelectTextureSGIS"); + + if (qglMTexCoord2fSGIS && qglSelectTextureSGIS) { + Con_Printf("Multitexture extensions found.\n"); + gl_mtexable = true; + } else + Con_Printf("Symbol not found, disabled.\n"); + + dlclose(prjobj); + } +} + +/* +=============== +GL_Init +=============== +*/ +void GL_Init (void) +{ + gl_vendor = glGetString (GL_VENDOR); + Con_Printf ("GL_VENDOR: %s\n", gl_vendor); + gl_renderer = glGetString (GL_RENDERER); + Con_Printf ("GL_RENDERER: %s\n", gl_renderer); + + gl_version = glGetString (GL_VERSION); + Con_Printf ("GL_VERSION: %s\n", gl_version); + gl_extensions = glGetString (GL_EXTENSIONS); + Con_Printf ("Printing GL_EXTENSIONS string was causing buffer overflow. Kind of fixed by not printing it at all."); + //Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); + +// Con_Printf ("%s %s\n", gl_renderer, gl_version); + + CheckMultiTextureExtensions (); + + glClearColor (1,0,0,0); + glCullFace(GL_FRONT); + glEnable(GL_TEXTURE_2D); + + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.666); + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glShadeModel (GL_FLAT); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +} + +/* +================= +GL_BeginRendering + +================= +*/ +void GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + extern cvar_t gl_clear; + + *x = *y = 0; + *width = scr_width; + *height = scr_height; + +// if (!wglMakeCurrent( maindc, baseRC )) +// Sys_Error ("wglMakeCurrent failed"); + +// glViewport (*x, *y, *width, *height); +} + + +void GL_EndRendering (void) +{ + glFlush(); + glXSwapBuffers(dpy, win); +} + +qboolean VID_Is8bit(void) +{ + return is8bit; +} + +void VID_Init8bitPalette(void) +{ + // Check for 8bit Extensions and initialize them. + int i; + void *prjobj; + + if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) { + Con_Printf("Unable to open symbol list for main program.\n"); + return; + } + + if (strstr(gl_extensions, "3DFX_set_global_palette") && + (qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL) { + GLubyte table[256][4]; + char *oldpal; + + Con_SafePrintf("8-bit GL extensions enabled.\n"); + glEnable( GL_SHARED_TEXTURE_PALETTE_EXT ); + oldpal = (char *) d_8to24table; //d_8to24table3dfx; + for (i=0;i<256;i++) { + table[i][2] = *oldpal++; + table[i][1] = *oldpal++; + table[i][0] = *oldpal++; + table[i][3] = 255; + oldpal++; + } + qgl3DfxSetPaletteEXT((GLuint *)table); + is8bit = true; + + } else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") && + (qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL) { + char thePalette[256*3]; + char *oldPalette, *newPalette; + + Con_SafePrintf("8-bit GL extensions enabled.\n"); + glEnable( GL_SHARED_TEXTURE_PALETTE_EXT ); + oldPalette = (char *) d_8to24table; //d_8to24table3dfx; + newPalette = thePalette; + for (i=0;i<256;i++) { + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + *newPalette++ = *oldPalette++; + oldPalette++; + } + qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette); + is8bit = true; + } + + dlclose(prjobj); +} + +static void Check_Gamma (unsigned char *pal) +{ + float f, inf; + unsigned char palette[768]; + int i; + + if ((i = COM_CheckParm("-gamma")) == 0) { + if ((gl_renderer && strstr(gl_renderer, "Voodoo")) || + (gl_vendor && strstr(gl_vendor, "3Dfx"))) + vid_gamma = 1; + else + vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware + } else + vid_gamma = Q_atof(com_argv[i+1]); + + for (i=0 ; i<768 ; i++) + { + f = pow ( (pal[i]+1)/256.0 , vid_gamma ); + inf = f*255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + palette[i] = inf; + } + + memcpy (pal, palette, sizeof(palette)); +} + +void VID_Init(unsigned char *palette) +{ + int i; + int attrib[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None + }; + char gldir[MAX_OSPATH]; + int width = 640, height = 480; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + XVisualInfo *visinfo; + qboolean fullscreen = true; + int MajorVersion, MinorVersion; + int actualWidth, actualHeight; + + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&in_mouse); + Cvar_RegisterVariable (&in_dgamouse); + Cvar_RegisterVariable (&m_filter); + Cvar_RegisterVariable (&gl_ztrick); + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + +// interpret command-line params + +// set vid parameters + if ((i = COM_CheckParm("-window")) != 0) + fullscreen = false; + + if ((i = COM_CheckParm("-width")) != 0) + width = atoi(com_argv[i+1]); + + if ((i = COM_CheckParm("-height")) != 0) + height = atoi(com_argv[i+1]); + + if ((i = COM_CheckParm("-conwidth")) != 0) + vid.conwidth = Q_atoi(com_argv[i+1]); + else + vid.conwidth = 640; + + vid.conwidth &= 0xfff8; // make it a multiple of eight + + if (vid.conwidth < 320) + vid.conwidth = 320; + + // pick a conheight that matches with correct aspect + vid.conheight = vid.conwidth*3 / 4; + + if ((i = COM_CheckParm("-conheight")) != 0) + vid.conheight = Q_atoi(com_argv[i+1]); + if (vid.conheight < 200) + vid.conheight = 200; + + if (!(dpy = XOpenDisplay(NULL))) { + fprintf(stderr, "Error couldn't open the X display\n"); + exit(1); + } + + scrnum = DefaultScreen(dpy); + root = RootWindow(dpy, scrnum); + + // Get video mode list + MajorVersion = MinorVersion = 0; + if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { + vidmode_ext = false; + } else { + Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion); + vidmode_ext = true; + } + + visinfo = glXChooseVisual(dpy, scrnum, attrib); + if (!visinfo) { + fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n"); + exit(1); + } + + if (vidmode_ext) { + int best_fit, best_dist, dist, x, y; + + XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); + + // Are we going fullscreen? If so, let's change video mode + if (fullscreen) { + best_dist = 9999999; + best_fit = -1; + + for (i = 0; i < num_vidmodes; i++) { + if (width > vidmodes[i]->hdisplay || + height > vidmodes[i]->vdisplay) + continue; + + x = width - vidmodes[i]->hdisplay; + y = height - vidmodes[i]->vdisplay; + dist = (x * x) + (y * y); + if (dist < best_dist) { + best_dist = dist; + best_fit = i; + } + } + + if (best_fit != -1) { + actualWidth = vidmodes[best_fit]->hdisplay; + actualHeight = vidmodes[best_fit]->vdisplay; + + // change to the mode + XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]); + vidmode_active = true; + + // Move the viewport to top left + XF86VidModeSetViewPort(dpy, scrnum, 0, 0); + } else + fullscreen = 0; + } + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); + attr.event_mask = X_MASK; + if (vidmode_active) { + mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | + CWEventMask | CWOverrideRedirect; + attr.override_redirect = True; + attr.backing_store = NotUseful; + attr.save_under = False; + } else + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow(dpy, root, 0, 0, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr); + XMapWindow(dpy, win); + + if (vidmode_active) { + XMoveWindow(dpy, win, 0, 0); + XRaiseWindow(dpy, win); + XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); + XFlush(dpy); + // Move the viewport to top left + XF86VidModeSetViewPort(dpy, scrnum, 0, 0); + } + mouse_avail = true; + XFlush(dpy); + + ctx = glXCreateContext(dpy, visinfo, NULL, True); + + glXMakeCurrent(dpy, win, ctx); + + scr_width = width; + scr_height = height; + + if (vid.conheight > height) + vid.conheight = height; + if (vid.conwidth > width) + vid.conwidth = width; + vid.width = vid.conwidth; + vid.height = vid.conheight; + + vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); + vid.numpages = 2; + + InitSig(); // trap evil signals + + GL_Init(); + + sprintf (gldir, "%s/glquake", com_gamedir); + Sys_mkdir (gldir); + + VID_SetPalette(palette); + + // Check for 3DFX Extensions and initialize them. + VID_Init8bitPalette(); + + Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); + + vid.recalc_refdef = 1; // force a surface cache flush +} + +void Sys_SendKeyEvents(void) +{ + HandleEvents(); +} + +void Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + +void IN_Init(void) +{ +} + +void IN_Shutdown(void) +{ +} + +/* +=========== +IN_Commands +=========== +*/ +void IN_Commands (void) +{ + if (!dpy || !win) + return; + + if (vidmode_active || key_dest == key_game) + IN_ActivateMouse(); + else + IN_DeactivateMouse (); +} + +/* +=========== +IN_Move +=========== +*/ +void IN_MouseMove (usercmd_t *cmd) +{ + if (!mouse_avail) + return; + + if (m_filter.value) + { + mx = (mx + old_mouse_x) * 0.5; + my = (my + old_mouse_y) * 0.5; + } + old_mouse_x = mx; + old_mouse_y = my; + + mx *= sensitivity.value; + my *= sensitivity.value; + +// add mouse X/Y movement to cmd + if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) + cmd->sidemove += m_side.value * mx; + else + cl.viewangles[YAW] -= m_yaw.value * mx; + + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * my; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * my; + else + cmd->forwardmove -= m_forward.value * my; + } + mx = my = 0; +} + +void IN_Move (usercmd_t *cmd) +{ + IN_MouseMove(cmd); +} + + diff --git a/WinQuake/gl_vidnt.c b/WinQuake/gl_vidnt.c index 932a68d..223b717 100644 --- a/WinQuake/gl_vidnt.c +++ b/WinQuake/gl_vidnt.c @@ -606,8 +606,8 @@ void GL_Init (void) gl_version = glGetString (GL_VERSION); Con_Printf ("GL_VERSION: %s\n", gl_version); gl_extensions = glGetString (GL_EXTENSIONS); - Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); - + //Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions); + Con_Printf ("GL_EXTENSIONS string was causing overflow when printed. Kind of fixed."); // Con_Printf ("%s %s\n", gl_renderer, gl_version); if (strnicmp(gl_renderer,"PowerVR",7)==0) diff --git a/WinQuake/gl_warp.c b/WinQuake/gl_warp.c index e8b96af..33f52a6 100644 --- a/WinQuake/gl_warp.c +++ b/WinQuake/gl_warp.c @@ -1,1092 +1,1092 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// gl_warp.c -- sky and water polygons - -#include "quakedef.h" - -extern model_t *loadmodel; - -int skytexturenum; - -int solidskytexture; -int alphaskytexture; -float speedscale; // for top sky and bottom sky - -msurface_t *warpface; - -extern cvar_t gl_subdivide_size; - -void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) -{ - int i, j; - float *v; - - mins[0] = mins[1] = mins[2] = 9999; - maxs[0] = maxs[1] = maxs[2] = -9999; - v = verts; - for (i=0 ; i maxs[j]) - maxs[j] = *v; - } -} - -void SubdividePolygon (int numverts, float *verts) -{ - int i, j, k; - vec3_t mins, maxs; - float m; - float *v; - vec3_t front[64], back[64]; - int f, b; - float dist[64]; - float frac; - glpoly_t *poly; - float s, t; - - if (numverts > 60) - Sys_Error ("numverts = %i", numverts); - - BoundPoly (numverts, verts, mins, maxs); - - for (i=0 ; i<3 ; i++) - { - m = (mins[i] + maxs[i]) * 0.5; - m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5); - if (maxs[i] - m < 8) - continue; - if (m - mins[i] < 8) - continue; - - // cut it - v = verts + i; - for (j=0 ; j= 0) - { - VectorCopy (v, front[f]); - f++; - } - if (dist[j] <= 0) - { - VectorCopy (v, back[b]); - b++; - } - if (dist[j] == 0 || dist[j+1] == 0) - continue; - if ( (dist[j] > 0) != (dist[j+1] > 0) ) - { - // clip point - frac = dist[j] / (dist[j] - dist[j+1]); - for (k=0 ; k<3 ; k++) - front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); - f++; - b++; - } - } - - SubdividePolygon (f, front[0]); - SubdividePolygon (b, back[0]); - return; - } - - poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); - poly->next = warpface->polys; - warpface->polys = poly; - poly->numverts = numverts; - for (i=0 ; iverts[i]); - s = DotProduct (verts, warpface->texinfo->vecs[0]); - t = DotProduct (verts, warpface->texinfo->vecs[1]); - poly->verts[i][3] = s; - poly->verts[i][4] = t; - } -} - -/* -================ -GL_SubdivideSurface - -Breaks a polygon up along axial 64 unit -boundaries so that turbulent and sky warps -can be done reasonably. -================ -*/ -void GL_SubdivideSurface (msurface_t *fa) -{ - vec3_t verts[64]; - int numverts; - int i; - int lindex; - float *vec; - texture_t *t; - - warpface = fa; - - // - // convert edges back to a normal polygon - // - numverts = 0; - for (i=0 ; inumedges ; i++) - { - lindex = loadmodel->surfedges[fa->firstedge + i]; - - if (lindex > 0) - vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; - else - vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; - VectorCopy (vec, verts[numverts]); - numverts++; - } - - SubdividePolygon (numverts, verts[0]); -} - -//========================================================= - - - -// speed up sin calculations - Ed -float turbsin[] = -{ - #include "gl_warp_sin.h" -}; -#define TURBSCALE (256.0 / (2 * M_PI)) - -/* -============= -EmitWaterPolys - -Does a water warp on the pre-fragmented glpoly_t chain -============= -*/ -void EmitWaterPolys (msurface_t *fa) -{ - glpoly_t *p; - float *v; - int i; - float s, t, os, ot; - - - for (p=fa->polys ; p ; p=p->next) - { - glBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - os = v[3]; - ot = v[4]; - - s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; - s *= (1.0/64); - - t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; - t *= (1.0/64); - - glTexCoord2f (s, t); - glVertex3fv (v); - } - glEnd (); - } -} - - - - -/* -============= -EmitSkyPolys -============= -*/ -void EmitSkyPolys (msurface_t *fa) -{ - glpoly_t *p; - float *v; - int i; - float s, t; - vec3_t dir; - float length; - - for (p=fa->polys ; p ; p=p->next) - { - glBegin (GL_POLYGON); - for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) - { - VectorSubtract (v, r_origin, dir); - dir[2] *= 3; // flatten the sphere - - length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; - length = sqrt (length); - length = 6*63/length; - - dir[0] *= length; - dir[1] *= length; - - s = (speedscale + dir[0]) * (1.0/128); - t = (speedscale + dir[1]) * (1.0/128); - - glTexCoord2f (s, t); - glVertex3fv (v); - } - glEnd (); - } -} - -/* -=============== -EmitBothSkyLayers - -Does a sky warp on the pre-fragmented glpoly_t chain -This will be called for brushmodels, the world -will have them chained together. -=============== -*/ -void EmitBothSkyLayers (msurface_t *fa) -{ - int i; - int lindex; - float *vec; - - GL_DisableMultitexture(); - - GL_Bind (solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale & ~127 ; - - EmitSkyPolys (fa); - - glEnable (GL_BLEND); - GL_Bind (alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale & ~127 ; - - EmitSkyPolys (fa); - - glDisable (GL_BLEND); -} - -#ifndef QUAKE2 -/* -================= -R_DrawSkyChain -================= -*/ -void R_DrawSkyChain (msurface_t *s) -{ - msurface_t *fa; - - GL_DisableMultitexture(); - - // used when gl_texsort is on - GL_Bind(solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale & ~127 ; - - for (fa=s ; fa ; fa=fa->texturechain) - EmitSkyPolys (fa); - - glEnable (GL_BLEND); - GL_Bind (alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale & ~127 ; - - for (fa=s ; fa ; fa=fa->texturechain) - EmitSkyPolys (fa); - - glDisable (GL_BLEND); -} - -#endif - -/* -================================================================= - - Quake 2 environment sky - -================================================================= -*/ - -#ifdef QUAKE2 - - -#define SKY_TEX 2000 - -/* -================================================================= - - PCX Loading - -================================================================= -*/ - -typedef struct -{ - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short hres,vres; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned data; // unbounded -} pcx_t; - -byte *pcx_rgb; - -/* -============ -LoadPCX -============ -*/ -void LoadPCX (FILE *f) -{ - pcx_t *pcx, pcxbuf; - byte palette[768]; - byte *pix; - int x, y; - int dataByte, runLength; - int count; - -// -// parse the PCX file -// - fread (&pcxbuf, 1, sizeof(pcxbuf), f); - - pcx = &pcxbuf; - - if (pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 - || pcx->xmax >= 320 - || pcx->ymax >= 256) - { - Con_Printf ("Bad pcx file\n"); - return; - } - - // seek to palette - fseek (f, -768, SEEK_END); - fread (palette, 1, 768, f); - - fseek (f, sizeof(pcxbuf) - 4, SEEK_SET); - - count = (pcx->xmax+1) * (pcx->ymax+1); - pcx_rgb = malloc( count * 4); - - for (y=0 ; y<=pcx->ymax ; y++) - { - pix = pcx_rgb + 4*y*(pcx->xmax+1); - for (x=0 ; x<=pcx->ymax ; ) - { - dataByte = fgetc(f); - - if((dataByte & 0xC0) == 0xC0) - { - runLength = dataByte & 0x3F; - dataByte = fgetc(f); - } - else - runLength = 1; - - while(runLength-- > 0) - { - pix[0] = palette[dataByte*3]; - pix[1] = palette[dataByte*3+1]; - pix[2] = palette[dataByte*3+2]; - pix[3] = 255; - pix += 4; - x++; - } - } - } -} - -/* -========================================================= - -TARGA LOADING - -========================================================= -*/ - -typedef struct _TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; -} TargaHeader; - - -TargaHeader targa_header; -byte *targa_rgba; - -int fgetLittleShort (FILE *f) -{ - byte b1, b2; - - b1 = fgetc(f); - b2 = fgetc(f); - - return (short)(b1 + b2*256); -} - -int fgetLittleLong (FILE *f) -{ - byte b1, b2, b3, b4; - - b1 = fgetc(f); - b2 = fgetc(f); - b3 = fgetc(f); - b4 = fgetc(f); - - return b1 + (b2<<8) + (b3<<16) + (b4<<24); -} - - -/* -============= -LoadTGA -============= -*/ -void LoadTGA (FILE *fin) -{ - int columns, rows, numPixels; - byte *pixbuf; - int row, column; - - targa_header.id_length = fgetc(fin); - targa_header.colormap_type = fgetc(fin); - targa_header.image_type = fgetc(fin); - - targa_header.colormap_index = fgetLittleShort(fin); - targa_header.colormap_length = fgetLittleShort(fin); - targa_header.colormap_size = fgetc(fin); - targa_header.x_origin = fgetLittleShort(fin); - targa_header.y_origin = fgetLittleShort(fin); - targa_header.width = fgetLittleShort(fin); - targa_header.height = fgetLittleShort(fin); - targa_header.pixel_size = fgetc(fin); - targa_header.attributes = fgetc(fin); - - if (targa_header.image_type!=2 - && targa_header.image_type!=10) - Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); - - if (targa_header.colormap_type !=0 - || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) - Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); - - columns = targa_header.width; - rows = targa_header.height; - numPixels = columns * rows; - - targa_rgba = malloc (numPixels*4); - - if (targa_header.id_length != 0) - fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment - - if (targa_header.image_type==2) { // Uncompressed, RGB images - for(row=rows-1; row>=0; row--) { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column=0; row--) { - pixbuf = targa_rgba + row*columns*4; - for(column=0; column0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - else { // non run-length packet - for(j=0;j0) - row--; - else - goto breakOut; - pixbuf = targa_rgba + row*columns*4; - } - } - } - } - breakOut:; - } - } - - fclose(fin); -} - -/* -================== -R_LoadSkys -================== -*/ -char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; -void R_LoadSkys (void) -{ - int i; - FILE *f; - char name[64]; - - for (i=0 ; i<6 ; i++) - { - GL_Bind (SKY_TEX + i); - sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]); - COM_FOpenFile (name, &f); - if (!f) - { - Con_Printf ("Couldn't load %s\n", name); - continue; - } - LoadTGA (f); -// LoadPCX (f); - - glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba); -// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb); - - free (targa_rgba); -// free (pcx_rgb); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } -} - - -vec3_t skyclip[6] = { - {1,1,0}, - {1,-1,0}, - {0,-1,1}, - {0,1,1}, - {1,0,1}, - {-1,0,1} -}; -int c_sky; - -// 1 = s, 2 = t, 3 = 2048 -int st_to_vec[6][3] = -{ - {3,-1,2}, - {-3,1,2}, - - {1,3,2}, - {-1,-3,2}, - - {-2,-1,3}, // 0 degrees yaw, look straight up - {2,-1,-3} // look straight down - -// {-1,2,3}, -// {1,2,-3} -}; - -// s = [0]/[2], t = [1]/[2] -int vec_to_st[6][3] = -{ - {-2,3,1}, - {2,3,-1}, - - {1,3,2}, - {-1,3,-2}, - - {-2,-1,3}, - {-2,1,-3} - -// {-1,2,3}, -// {1,2,-3} -}; - -float skymins[2][6], skymaxs[2][6]; - -void DrawSkyPolygon (int nump, vec3_t vecs) -{ - int i,j; - vec3_t v, av; - float s, t, dv; - int axis; - float *vp; - - c_sky++; -#if 0 -glBegin (GL_POLYGON); -for (i=0 ; i av[1] && av[0] > av[2]) - { - if (v[0] < 0) - axis = 1; - else - axis = 0; - } - else if (av[1] > av[2] && av[1] > av[0]) - { - if (v[1] < 0) - axis = 3; - else - axis = 2; - } - else - { - if (v[2] < 0) - axis = 5; - else - axis = 4; - } - - // project new texture coords - for (i=0 ; i 0) - dv = vecs[j - 1]; - else - dv = -vecs[-j - 1]; - - j = vec_to_st[axis][0]; - if (j < 0) - s = -vecs[-j -1] / dv; - else - s = vecs[j-1] / dv; - j = vec_to_st[axis][1]; - if (j < 0) - t = -vecs[-j -1] / dv; - else - t = vecs[j-1] / dv; - - if (s < skymins[0][axis]) - skymins[0][axis] = s; - if (t < skymins[1][axis]) - skymins[1][axis] = t; - if (s > skymaxs[0][axis]) - skymaxs[0][axis] = s; - if (t > skymaxs[1][axis]) - skymaxs[1][axis] = t; - } -} - -#define MAX_CLIP_VERTS 64 -void ClipSkyPolygon (int nump, vec3_t vecs, int stage) -{ - float *norm; - float *v; - qboolean front, back; - float d, e; - float dists[MAX_CLIP_VERTS]; - int sides[MAX_CLIP_VERTS]; - vec3_t newv[2][MAX_CLIP_VERTS]; - int newc[2]; - int i, j; - - if (nump > MAX_CLIP_VERTS-2) - Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS"); - if (stage == 6) - { // fully clipped, so draw it - DrawSkyPolygon (nump, vecs); - return; - } - - front = back = false; - norm = skyclip[stage]; - for (i=0, v = vecs ; i ON_EPSILON) - { - front = true; - sides[i] = SIDE_FRONT; - } - else if (d < ON_EPSILON) - { - back = true; - sides[i] = SIDE_BACK; - } - else - sides[i] = SIDE_ON; - dists[i] = d; - } - - if (!front || !back) - { // not clipped - ClipSkyPolygon (nump, vecs, stage+1); - return; - } - - // clip it - sides[i] = sides[0]; - dists[i] = dists[0]; - VectorCopy (vecs, (vecs+(i*3)) ); - newc[0] = newc[1] = 0; - - for (i=0, v = vecs ; itexturechain) - { - for (p=fa->polys ; p ; p=p->next) - { - for (i=0 ; inumverts ; i++) - { - VectorSubtract (p->verts[i], r_origin, verts[i]); - } - ClipSkyPolygon (p->numverts, verts[0], 0); - } - } -} - - -/* -============== -R_ClearSkyBox -============== -*/ -void R_ClearSkyBox (void) -{ - int i; - - for (i=0 ; i<6 ; i++) - { - skymins[0][i] = skymins[1][i] = 9999; - skymaxs[0][i] = skymaxs[1][i] = -9999; - } -} - - -void MakeSkyVec (float s, float t, int axis) -{ - vec3_t v, b; - int j, k; - - b[0] = s*2048; - b[1] = t*2048; - b[2] = 2048; - - for (j=0 ; j<3 ; j++) - { - k = st_to_vec[axis][j]; - if (k < 0) - v[j] = -b[-k - 1]; - else - v[j] = b[k - 1]; - v[j] += r_origin[j]; - } - - // avoid bilerp seam - s = (s+1)*0.5; - t = (t+1)*0.5; - - if (s < 1.0/512) - s = 1.0/512; - else if (s > 511.0/512) - s = 511.0/512; - if (t < 1.0/512) - t = 1.0/512; - else if (t > 511.0/512) - t = 511.0/512; - - t = 1.0 - t; - glTexCoord2f (s, t); - glVertex3fv (v); -} - -/* -============== -R_DrawSkyBox -============== -*/ -int skytexorder[6] = {0,2,1,3,4,5}; -void R_DrawSkyBox (void) -{ - int i, j, k; - vec3_t v; - float s, t; - -#if 0 -glEnable (GL_BLEND); -glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -glColor4f (1,1,1,0.5); -glDisable (GL_DEPTH_TEST); -#endif - for (i=0 ; i<6 ; i++) - { - if (skymins[0][i] >= skymaxs[0][i] - || skymins[1][i] >= skymaxs[1][i]) - continue; - - GL_Bind (SKY_TEX+skytexorder[i]); -#if 0 -skymins[0][i] = -1; -skymins[1][i] = -1; -skymaxs[0][i] = 1; -skymaxs[1][i] = 1; -#endif - glBegin (GL_QUADS); - MakeSkyVec (skymins[0][i], skymins[1][i], i); - MakeSkyVec (skymins[0][i], skymaxs[1][i], i); - MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); - MakeSkyVec (skymaxs[0][i], skymins[1][i], i); - glEnd (); - } -#if 0 -glDisable (GL_BLEND); -glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -glColor4f (1,1,1,0.5); -glEnable (GL_DEPTH_TEST); -#endif -} - - -#endif - -//=============================================================== - -/* -============= -R_InitSky - -A sky texture is 256*128, with the right side being a masked overlay -============== -*/ -void R_InitSky (texture_t *mt) -{ - int i, j, p; - byte *src; - unsigned trans[128*128]; - unsigned transpix; - int r, g, b; - unsigned *rgba; - extern int skytexturenum; - - src = (byte *)mt + mt->offsets[0]; - - // make an average value for the back to avoid - // a fringe on the top level - - r = g = b = 0; - for (i=0 ; i<128 ; i++) - for (j=0 ; j<128 ; j++) - { - p = src[i*256 + j + 128]; - rgba = &d_8to24table[p]; - trans[(i*128) + j] = *rgba; - r += ((byte *)rgba)[0]; - g += ((byte *)rgba)[1]; - b += ((byte *)rgba)[2]; - } - - ((byte *)&transpix)[0] = r/(128*128); - ((byte *)&transpix)[1] = g/(128*128); - ((byte *)&transpix)[2] = b/(128*128); - ((byte *)&transpix)[3] = 0; - - - if (!solidskytexture) - solidskytexture = texture_extension_number++; - GL_Bind (solidskytexture ); - glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - - for (i=0 ; i<128 ; i++) - for (j=0 ; j<128 ; j++) - { - p = src[i*256 + j]; - if (p == 0) - trans[(i*128) + j] = transpix; - else - trans[(i*128) + j] = d_8to24table[p]; - } - - if (!alphaskytexture) - alphaskytexture = texture_extension_number++; - GL_Bind(alphaskytexture); - glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// gl_warp.c -- sky and water polygons + +#include "quakedef.h" + +extern model_t *loadmodel; + +int skytexturenum; + +int solidskytexture; +int alphaskytexture; +float speedscale; // for top sky and bottom sky + +msurface_t *warpface; + +extern cvar_t gl_subdivide_size; + +void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) +{ + int i, j; + float *v; + + mins[0] = mins[1] = mins[2] = 9999; + maxs[0] = maxs[1] = maxs[2] = -9999; + v = verts; + for (i=0 ; i maxs[j]) + maxs[j] = *v; + } +} + +void SubdividePolygon (int numverts, float *verts) +{ + int i, j, k; + vec3_t mins, maxs; + float m; + float *v; + vec3_t front[64], back[64]; + int f, b; + float dist[64]; + float frac; + glpoly_t *poly; + float s, t; + + if (numverts > 60) + Sys_Error ("numverts = %i", numverts); + + BoundPoly (numverts, verts, mins, maxs); + + for (i=0 ; i<3 ; i++) + { + m = (mins[i] + maxs[i]) * 0.5; + m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5); + if (maxs[i] - m < 8) + continue; + if (m - mins[i] < 8) + continue; + + // cut it + v = verts + i; + for (j=0 ; j= 0) + { + VectorCopy (v, front[f]); + f++; + } + if (dist[j] <= 0) + { + VectorCopy (v, back[b]); + b++; + } + if (dist[j] == 0 || dist[j+1] == 0) + continue; + if ( (dist[j] > 0) != (dist[j+1] > 0) ) + { + // clip point + frac = dist[j] / (dist[j] - dist[j+1]); + for (k=0 ; k<3 ; k++) + front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); + f++; + b++; + } + } + + SubdividePolygon (f, front[0]); + SubdividePolygon (b, back[0]); + return; + } + + poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); + poly->next = warpface->polys; + warpface->polys = poly; + poly->numverts = numverts; + for (i=0 ; iverts[i]); + s = DotProduct (verts, warpface->texinfo->vecs[0]); + t = DotProduct (verts, warpface->texinfo->vecs[1]); + poly->verts[i][3] = s; + poly->verts[i][4] = t; + } +} + +/* +================ +GL_SubdivideSurface + +Breaks a polygon up along axial 64 unit +boundaries so that turbulent and sky warps +can be done reasonably. +================ +*/ +void GL_SubdivideSurface (msurface_t *fa) +{ + vec3_t verts[64]; + int numverts; + int i; + int lindex; + float *vec; + texture_t *t; + + warpface = fa; + + // + // convert edges back to a normal polygon + // + numverts = 0; + for (i=0 ; inumedges ; i++) + { + lindex = loadmodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; + else + vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; + VectorCopy (vec, verts[numverts]); + numverts++; + } + + SubdividePolygon (numverts, verts[0]); +} + +//========================================================= + + + +// speed up sin calculations - Ed +float turbsin[] = +{ + #include "gl_warp_sin.h" +}; +#define TURBSCALE (256.0 / (2 * M_PI)) + +/* +============= +EmitWaterPolys + +Does a water warp on the pre-fragmented glpoly_t chain +============= +*/ +void EmitWaterPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t, os, ot; + + + for (p=fa->polys ; p ; p=p->next) + { + glBegin (GL_POLYGON); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + os = v[3]; + ot = v[4]; + + s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; + s *= (1.0/64); + + t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; + t *= (1.0/64); + + glTexCoord2f (s, t); + glVertex3fv (v); + } + glEnd (); + } +} + + + + +/* +============= +EmitSkyPolys +============= +*/ +void EmitSkyPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t; + vec3_t dir; + float length; + + for (p=fa->polys ; p ; p=p->next) + { + glBegin (GL_POLYGON); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + VectorSubtract (v, r_origin, dir); + dir[2] *= 3; // flatten the sphere + + length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; + length = sqrt (length); + length = 6*63/length; + + dir[0] *= length; + dir[1] *= length; + + s = (speedscale + dir[0]) * (1.0/128); + t = (speedscale + dir[1]) * (1.0/128); + + glTexCoord2f (s, t); + glVertex3fv (v); + } + glEnd (); + } +} + +/* +=============== +EmitBothSkyLayers + +Does a sky warp on the pre-fragmented glpoly_t chain +This will be called for brushmodels, the world +will have them chained together. +=============== +*/ +void EmitBothSkyLayers (msurface_t *fa) +{ + int i; + int lindex; + float *vec; + + GL_DisableMultitexture(); + + GL_Bind (solidskytexture); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + glEnable (GL_BLEND); + GL_Bind (alphaskytexture); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + glDisable (GL_BLEND); +} + +#ifndef QUAKE2 +/* +================= +R_DrawSkyChain +================= +*/ +void R_DrawSkyChain (msurface_t *s) +{ + msurface_t *fa; + + GL_DisableMultitexture(); + + // used when gl_texsort is on + GL_Bind(solidskytexture); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + glEnable (GL_BLEND); + GL_Bind (alphaskytexture); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + glDisable (GL_BLEND); +} + +#endif + +/* +================================================================= + + Quake 2 environment sky + +================================================================= +*/ + +#ifdef QUAKE2 + + +#define SKY_TEX 2000 + +/* +================================================================= + + PCX Loading + +================================================================= +*/ + +typedef struct +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + unsigned short xmin,ymin,xmax,ymax; + unsigned short hres,vres; + unsigned char palette[48]; + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + char filler[58]; + unsigned data; // unbounded +} pcx_t; + +byte *pcx_rgb; + +/* +============ +LoadPCX +============ +*/ +void LoadPCX (FILE *f) +{ + pcx_t *pcx, pcxbuf; + byte palette[768]; + byte *pix; + int x, y; + int dataByte, runLength; + int count; + +// +// parse the PCX file +// + fread (&pcxbuf, 1, sizeof(pcxbuf), f); + + pcx = &pcxbuf; + + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8 + || pcx->xmax >= 320 + || pcx->ymax >= 256) + { + Con_Printf ("Bad pcx file\n"); + return; + } + + // seek to palette + fseek (f, -768, SEEK_END); + fread (palette, 1, 768, f); + + fseek (f, sizeof(pcxbuf) - 4, SEEK_SET); + + count = (pcx->xmax+1) * (pcx->ymax+1); + pcx_rgb = malloc( count * 4); + + for (y=0 ; y<=pcx->ymax ; y++) + { + pix = pcx_rgb + 4*y*(pcx->xmax+1); + for (x=0 ; x<=pcx->ymax ; ) + { + dataByte = fgetc(f); + + if((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = fgetc(f); + } + else + runLength = 1; + + while(runLength-- > 0) + { + pix[0] = palette[dataByte*3]; + pix[1] = palette[dataByte*3+1]; + pix[2] = palette[dataByte*3+2]; + pix[3] = 255; + pix += 4; + x++; + } + } + } +} + +/* +========================================================= + +TARGA LOADING + +========================================================= +*/ + +typedef struct _TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; +} TargaHeader; + + +TargaHeader targa_header; +byte *targa_rgba; + +int fgetLittleShort (FILE *f) +{ + byte b1, b2; + + b1 = fgetc(f); + b2 = fgetc(f); + + return (short)(b1 + b2*256); +} + +int fgetLittleLong (FILE *f) +{ + byte b1, b2, b3, b4; + + b1 = fgetc(f); + b2 = fgetc(f); + b3 = fgetc(f); + b4 = fgetc(f); + + return b1 + (b2<<8) + (b3<<16) + (b4<<24); +} + + +/* +============= +LoadTGA +============= +*/ +void LoadTGA (FILE *fin) +{ + int columns, rows, numPixels; + byte *pixbuf; + int row, column; + + targa_header.id_length = fgetc(fin); + targa_header.colormap_type = fgetc(fin); + targa_header.image_type = fgetc(fin); + + targa_header.colormap_index = fgetLittleShort(fin); + targa_header.colormap_length = fgetLittleShort(fin); + targa_header.colormap_size = fgetc(fin); + targa_header.x_origin = fgetLittleShort(fin); + targa_header.y_origin = fgetLittleShort(fin); + targa_header.width = fgetLittleShort(fin); + targa_header.height = fgetLittleShort(fin); + targa_header.pixel_size = fgetc(fin); + targa_header.attributes = fgetc(fin); + + if (targa_header.image_type!=2 + && targa_header.image_type!=10) + Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); + + if (targa_header.colormap_type !=0 + || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) + Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); + + columns = targa_header.width; + rows = targa_header.height; + numPixels = columns * rows; + + targa_rgba = malloc (numPixels*4); + + if (targa_header.id_length != 0) + fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment + + if (targa_header.image_type==2) { // Uncompressed, RGB images + for(row=rows-1; row>=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column=0; row--) { + pixbuf = targa_rgba + row*columns*4; + for(column=0; column0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + else { // non run-length packet + for(j=0;j0) + row--; + else + goto breakOut; + pixbuf = targa_rgba + row*columns*4; + } + } + } + } + breakOut:; + } + } + + fclose(fin); +} + +/* +================== +R_LoadSkys +================== +*/ +char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; +void R_LoadSkys (void) +{ + int i; + FILE *f; + char name[64]; + + for (i=0 ; i<6 ; i++) + { + GL_Bind (SKY_TEX + i); + sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]); + COM_FOpenFile (name, &f); + if (!f) + { + Con_Printf ("Couldn't load %s\n", name); + continue; + } + LoadTGA (f); +// LoadPCX (f); + + glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba); +// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb); + + free (targa_rgba); +// free (pcx_rgb); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } +} + + +vec3_t skyclip[6] = { + {1,1,0}, + {1,-1,0}, + {0,-1,1}, + {0,1,1}, + {1,0,1}, + {-1,0,1} +}; +int c_sky; + +// 1 = s, 2 = t, 3 = 2048 +int st_to_vec[6][3] = +{ + {3,-1,2}, + {-3,1,2}, + + {1,3,2}, + {-1,-3,2}, + + {-2,-1,3}, // 0 degrees yaw, look straight up + {2,-1,-3} // look straight down + +// {-1,2,3}, +// {1,2,-3} +}; + +// s = [0]/[2], t = [1]/[2] +int vec_to_st[6][3] = +{ + {-2,3,1}, + {2,3,-1}, + + {1,3,2}, + {-1,3,-2}, + + {-2,-1,3}, + {-2,1,-3} + +// {-1,2,3}, +// {1,2,-3} +}; + +float skymins[2][6], skymaxs[2][6]; + +void DrawSkyPolygon (int nump, vec3_t vecs) +{ + int i,j; + vec3_t v, av; + float s, t, dv; + int axis; + float *vp; + + c_sky++; +#if 0 +glBegin (GL_POLYGON); +for (i=0 ; i av[1] && av[0] > av[2]) + { + if (v[0] < 0) + axis = 1; + else + axis = 0; + } + else if (av[1] > av[2] && av[1] > av[0]) + { + if (v[1] < 0) + axis = 3; + else + axis = 2; + } + else + { + if (v[2] < 0) + axis = 5; + else + axis = 4; + } + + // project new texture coords + for (i=0 ; i 0) + dv = vecs[j - 1]; + else + dv = -vecs[-j - 1]; + + j = vec_to_st[axis][0]; + if (j < 0) + s = -vecs[-j -1] / dv; + else + s = vecs[j-1] / dv; + j = vec_to_st[axis][1]; + if (j < 0) + t = -vecs[-j -1] / dv; + else + t = vecs[j-1] / dv; + + if (s < skymins[0][axis]) + skymins[0][axis] = s; + if (t < skymins[1][axis]) + skymins[1][axis] = t; + if (s > skymaxs[0][axis]) + skymaxs[0][axis] = s; + if (t > skymaxs[1][axis]) + skymaxs[1][axis] = t; + } +} + +#define MAX_CLIP_VERTS 64 +void ClipSkyPolygon (int nump, vec3_t vecs, int stage) +{ + float *norm; + float *v; + qboolean front, back; + float d, e; + float dists[MAX_CLIP_VERTS]; + int sides[MAX_CLIP_VERTS]; + vec3_t newv[2][MAX_CLIP_VERTS]; + int newc[2]; + int i, j; + + if (nump > MAX_CLIP_VERTS-2) + Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS"); + if (stage == 6) + { // fully clipped, so draw it + DrawSkyPolygon (nump, vecs); + return; + } + + front = back = false; + norm = skyclip[stage]; + for (i=0, v = vecs ; i ON_EPSILON) + { + front = true; + sides[i] = SIDE_FRONT; + } + else if (d < ON_EPSILON) + { + back = true; + sides[i] = SIDE_BACK; + } + else + sides[i] = SIDE_ON; + dists[i] = d; + } + + if (!front || !back) + { // not clipped + ClipSkyPolygon (nump, vecs, stage+1); + return; + } + + // clip it + sides[i] = sides[0]; + dists[i] = dists[0]; + VectorCopy (vecs, (vecs+(i*3)) ); + newc[0] = newc[1] = 0; + + for (i=0, v = vecs ; itexturechain) + { + for (p=fa->polys ; p ; p=p->next) + { + for (i=0 ; inumverts ; i++) + { + VectorSubtract (p->verts[i], r_origin, verts[i]); + } + ClipSkyPolygon (p->numverts, verts[0], 0); + } + } +} + + +/* +============== +R_ClearSkyBox +============== +*/ +void R_ClearSkyBox (void) +{ + int i; + + for (i=0 ; i<6 ; i++) + { + skymins[0][i] = skymins[1][i] = 9999; + skymaxs[0][i] = skymaxs[1][i] = -9999; + } +} + + +void MakeSkyVec (float s, float t, int axis) +{ + vec3_t v, b; + int j, k; + + b[0] = s*2048; + b[1] = t*2048; + b[2] = 2048; + + for (j=0 ; j<3 ; j++) + { + k = st_to_vec[axis][j]; + if (k < 0) + v[j] = -b[-k - 1]; + else + v[j] = b[k - 1]; + v[j] += r_origin[j]; + } + + // avoid bilerp seam + s = (s+1)*0.5; + t = (t+1)*0.5; + + if (s < 1.0/512) + s = 1.0/512; + else if (s > 511.0/512) + s = 511.0/512; + if (t < 1.0/512) + t = 1.0/512; + else if (t > 511.0/512) + t = 511.0/512; + + t = 1.0 - t; + glTexCoord2f (s, t); + glVertex3fv (v); +} + +/* +============== +R_DrawSkyBox +============== +*/ +int skytexorder[6] = {0,2,1,3,4,5}; +void R_DrawSkyBox (void) +{ + int i, j, k; + vec3_t v; + float s, t; + +#if 0 +glEnable (GL_BLEND); +glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +glColor4f (1,1,1,0.5); +glDisable (GL_DEPTH_TEST); +#endif + for (i=0 ; i<6 ; i++) + { + if (skymins[0][i] >= skymaxs[0][i] + || skymins[1][i] >= skymaxs[1][i]) + continue; + + GL_Bind (SKY_TEX+skytexorder[i]); +#if 0 +skymins[0][i] = -1; +skymins[1][i] = -1; +skymaxs[0][i] = 1; +skymaxs[1][i] = 1; +#endif + glBegin (GL_QUADS); + MakeSkyVec (skymins[0][i], skymins[1][i], i); + MakeSkyVec (skymins[0][i], skymaxs[1][i], i); + MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); + MakeSkyVec (skymaxs[0][i], skymins[1][i], i); + glEnd (); + } +#if 0 +glDisable (GL_BLEND); +glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +glColor4f (1,1,1,0.5); +glEnable (GL_DEPTH_TEST); +#endif +} + + +#endif + +//=============================================================== + +/* +============= +R_InitSky + +A sky texture is 256*128, with the right side being a masked overlay +============== +*/ +void R_InitSky (texture_t *mt) +{ + int i, j, p; + byte *src; + unsigned trans[128*128]; + unsigned transpix; + int r, g, b; + unsigned *rgba; + extern int skytexturenum; + + src = (byte *)mt + mt->offsets[0]; + + // make an average value for the back to avoid + // a fringe on the top level + + r = g = b = 0; + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + { + p = src[i*256 + j + 128]; + rgba = &d_8to24table[p]; + trans[(i*128) + j] = *rgba; + r += ((byte *)rgba)[0]; + g += ((byte *)rgba)[1]; + b += ((byte *)rgba)[2]; + } + + ((byte *)&transpix)[0] = r/(128*128); + ((byte *)&transpix)[1] = g/(128*128); + ((byte *)&transpix)[2] = b/(128*128); + ((byte *)&transpix)[3] = 0; + + + if (!solidskytexture) + solidskytexture = texture_extension_number++; + GL_Bind (solidskytexture ); + glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + { + p = src[i*256 + j]; + if (p == 0) + trans[(i*128) + j] = transpix; + else + trans[(i*128) + j] = d_8to24table[p]; + } + + if (!alphaskytexture) + alphaskytexture = texture_extension_number++; + GL_Bind(alphaskytexture); + glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +} + diff --git a/WinQuake/gl_warp_sin.h b/WinQuake/gl_warp_sin.h index 22976a7..fa3e62a 100644 --- a/WinQuake/gl_warp_sin.h +++ b/WinQuake/gl_warp_sin.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ 0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677, 1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916, 3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998, diff --git a/WinQuake/glqnotes.txt b/WinQuake/glqnotes.txt index 2224072..957c0d6 100644 --- a/WinQuake/glqnotes.txt +++ b/WinQuake/glqnotes.txt @@ -1,171 +1,171 @@ -Glquake v0.99, Quake v1.09 release notes - -3dfx owners -- read the 3dfx.txt file. - -On a standard OpenGL system, all you should need to do to run glquake is put -glquake.exe in your quake directory, and run it from there. DO NOT install -the opengl32.dll unless you have a 3dfx! Glquake should change the screen -resolution to 640*480*32k colors and run full screen by default. - -If you are running win-95, your desktop must be set to 32k or 64k colors -before running glquake. NT can switch automatically. - -Theoretically, glquake will run on any compliant OpenGL that supports the -texture objects extensions, but unless it is very powerfull hardware that -accelerates everything needed, the game play will not be acceptable. If it -has to go through any software emulation paths, the performance will likely -by well under one frame per second. - -3dfx has provided an opengl32.dll that implements everything glquake needs, -but it is not a full opengl implementation. Other opengl applications are -very unlikely to work with it, so consider it basically a "glquake driver". -See the encluded 3dfx.txt for specific instalation notes. 3dfx can only run -full screen, but you must still have your desktop set to a 16 bit color mode -for glquake to start. - -resolution options ------------------- -We had dynamic resolution changing in glquake for a while, but every single -opengl driver I tried it on messed up in one way or another, so it is now -limited to startup time only. - -glquake -window -This will start glquake in a window on your desktop instead of switching the -screen to lower resolution and covering everything. - -glquake -width 800 -height 600 -Tries to run glquake at the specified resolution. Combined with -window, it -creates a desktop window that size, otherwise it tries to set a full screen -resolution. - -You can also specify the resolution of the console independant of the screen -resolution. - -glquake -conwidth 320 -This will specify a console resolution of 320 by 240 (the height is -automatically determined by the default 4:3 aspect ratio, you can also -specify the height directly with -conheight). - -In higher resolution modes such as 800x600 and 1024x768, glquake will default -to a 640x480 console, since the font becomes small enough at higher -resolutions to become unreadable. If do you wish to have a higher resolution -console and status bar, specify it as well, such as: -glquake -width 800 -height 600 -conwidth 800 - -texture options ---------------- -The amount of textures used in the game can have a large impact on performance. -There are several options that let you trade off visual quality for better -performance. - -There is no way to flush already loaded textures, so it is best to change -these options on the command line, or they will only take effect on some of -the textures when you change levels. - -OpenGL only allows textures to repeat on power of two boundaries (32, 64, -128, etc), but software quake had a number of textures that repeated at 24 -or 96 pixel boundaries. These need to be either stretched out to the next -higher size, or shrunk down to the next lower. By default, they are filtered -down to the smaller size, but you can cause it to use the larger size if you -really want by using: - -glquake +gl_round_down 0 -This will generally run well on a normal 4 MB 3dfx card, but for other cards -that have either worse texture management or slower texture swapping speeds, -there are some additional settings that can drastically lower the amount of -textures to be managed. - -glquake +gl_picmip 1 -This causes all textures to have one half the dimensions they otherwise would. -This makes them blurry, but very small. You can set this to 2 to make the -textures one quarter the resolution on each axis for REALLY blurry textures. - -glquake +gl_playermip 1 -This is similar to picmip, but is only used for other players in deathmatch. -Each player in a deathmatch requires an individual skin texture, so this can -be a serious problem for texture management. It wouldn't be unreasonable to -set this to 2 or even 3 if you are playing competatively (and don't care if -the other guys have smudged skins). If you change this during the game, it -will take effect as soon as a player changes their skin colors. - -GLQuake also supports the following extensions for faster texture operation: - -GL_SGIS_multitexture -Multitextures support allows certain hardware to render the world in one -pass instead of two. GLQuake uses two passes, one for the world textures -and the second for the lightmaps that are blended on the textures. On some -hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this -can be done in one pass. On hardware that supports this, you will get a -60% to 100% increase in frame rate. Currently, only 3DFX dual TMU cards -(such as the Obsidian 2220) support this extension, but other hardware will -soon follow. - -This extension will be autodetected and used. If for some reason it is not -working correctly, specify the command line option "-nomtex" to disable it. - -GL_EXT_shared_texture_palette -GLQuake uses 16bit textures by default but on OpenGL implementations -that support the GL_EXT_shared_texture_palette extension, GLQuake will use -8bit textures instead. This results in using half the needed texture memory -of 16bit texture and can improve performance. This is very little difference -in visual quality due to the fact that the textures are 8bit sources to -begin with. - -run time options ----------------- -At the console, you can set these values to effect drawing. - -gl_texturemode GL_NEAREST -Sets texture mapping to point sampled, which may be faster on some GL systems -(not on 3dfx). - -gl_texturemode GL_LINEAR_MIPMAP -This is the default texture mode. - -gl_texturemode GL_LINEAR_MIPMAP_LINEAR -This is the highest quality texture mapping (trilinear), but only very high -end hardware (intergraph intense 3D / realizm) supports it. Not that big of -a deal, actually. - -gl_finish 0 -This causes the game to not issue a glFinish() call each frame, which may make -some hardware run faster. If this is cleared, the 3dfx will back up a number -of frames and not be very playable. - -gl_flashblend 0 -By default, glquake just draws a shaded ball around objects that are emiting -light. Clearing this variable will cause it to properly relight the world -like normal quake, but it can be a significant speed hit on some systems. - -gl_ztrick 0 -Glquake uses a buffering method that avoids clearing the Z buffer, but some -hardware platforms don't like it. If the status bar and console are flashing -every other frame, clear this variable. - -gl_keeptjunctions 0 -If you clear this, glquake will remove colinear vertexes when it reloads the -level. This can give a few percent speedup, but it can leave a couple stray -blinking pixels on the screen. - -novelty features ----------------- -These are some rendering tricks that were easy to do in glquake. They aren't -very robust, but they are pretty cool to look at. - -r_shadows 1 -This causes every object to cast a shadow. - -r_wateralpha 0.7 -This sets the opacity of water textures, so you can see through it in properly -processed maps. 0.3 is very faint, almost like fog. 1 is completely solid -(the default). Unfortunately, the standard quake maps don't contain any -visibility information for seeing past water surfaces, so you can't just play -quake with this turned on. If you just want to see what it looks like, you -can set "r_novis 1", but that will make things go very slow. When I get a -chance, I will probably release some maps that have been processed properly -for this. - -r_mirroralpha 0.3 -This changes one particular texture (the stained glass texture in the EASY -start hall) into a mirror. The value is the opacity of the mirror surface. - +Glquake v0.99, Quake v1.09 release notes + +3dfx owners -- read the 3dfx.txt file. + +On a standard OpenGL system, all you should need to do to run glquake is put +glquake.exe in your quake directory, and run it from there. DO NOT install +the opengl32.dll unless you have a 3dfx! Glquake should change the screen +resolution to 640*480*32k colors and run full screen by default. + +If you are running win-95, your desktop must be set to 32k or 64k colors +before running glquake. NT can switch automatically. + +Theoretically, glquake will run on any compliant OpenGL that supports the +texture objects extensions, but unless it is very powerfull hardware that +accelerates everything needed, the game play will not be acceptable. If it +has to go through any software emulation paths, the performance will likely +by well under one frame per second. + +3dfx has provided an opengl32.dll that implements everything glquake needs, +but it is not a full opengl implementation. Other opengl applications are +very unlikely to work with it, so consider it basically a "glquake driver". +See the encluded 3dfx.txt for specific instalation notes. 3dfx can only run +full screen, but you must still have your desktop set to a 16 bit color mode +for glquake to start. + +resolution options +------------------ +We had dynamic resolution changing in glquake for a while, but every single +opengl driver I tried it on messed up in one way or another, so it is now +limited to startup time only. + +glquake -window +This will start glquake in a window on your desktop instead of switching the +screen to lower resolution and covering everything. + +glquake -width 800 -height 600 +Tries to run glquake at the specified resolution. Combined with -window, it +creates a desktop window that size, otherwise it tries to set a full screen +resolution. + +You can also specify the resolution of the console independant of the screen +resolution. + +glquake -conwidth 320 +This will specify a console resolution of 320 by 240 (the height is +automatically determined by the default 4:3 aspect ratio, you can also +specify the height directly with -conheight). + +In higher resolution modes such as 800x600 and 1024x768, glquake will default +to a 640x480 console, since the font becomes small enough at higher +resolutions to become unreadable. If do you wish to have a higher resolution +console and status bar, specify it as well, such as: +glquake -width 800 -height 600 -conwidth 800 + +texture options +--------------- +The amount of textures used in the game can have a large impact on performance. +There are several options that let you trade off visual quality for better +performance. + +There is no way to flush already loaded textures, so it is best to change +these options on the command line, or they will only take effect on some of +the textures when you change levels. + +OpenGL only allows textures to repeat on power of two boundaries (32, 64, +128, etc), but software quake had a number of textures that repeated at 24 +or 96 pixel boundaries. These need to be either stretched out to the next +higher size, or shrunk down to the next lower. By default, they are filtered +down to the smaller size, but you can cause it to use the larger size if you +really want by using: + +glquake +gl_round_down 0 +This will generally run well on a normal 4 MB 3dfx card, but for other cards +that have either worse texture management or slower texture swapping speeds, +there are some additional settings that can drastically lower the amount of +textures to be managed. + +glquake +gl_picmip 1 +This causes all textures to have one half the dimensions they otherwise would. +This makes them blurry, but very small. You can set this to 2 to make the +textures one quarter the resolution on each axis for REALLY blurry textures. + +glquake +gl_playermip 1 +This is similar to picmip, but is only used for other players in deathmatch. +Each player in a deathmatch requires an individual skin texture, so this can +be a serious problem for texture management. It wouldn't be unreasonable to +set this to 2 or even 3 if you are playing competatively (and don't care if +the other guys have smudged skins). If you change this during the game, it +will take effect as soon as a player changes their skin colors. + +GLQuake also supports the following extensions for faster texture operation: + +GL_SGIS_multitexture +Multitextures support allows certain hardware to render the world in one +pass instead of two. GLQuake uses two passes, one for the world textures +and the second for the lightmaps that are blended on the textures. On some +hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this +can be done in one pass. On hardware that supports this, you will get a +60% to 100% increase in frame rate. Currently, only 3DFX dual TMU cards +(such as the Obsidian 2220) support this extension, but other hardware will +soon follow. + +This extension will be autodetected and used. If for some reason it is not +working correctly, specify the command line option "-nomtex" to disable it. + +GL_EXT_shared_texture_palette +GLQuake uses 16bit textures by default but on OpenGL implementations +that support the GL_EXT_shared_texture_palette extension, GLQuake will use +8bit textures instead. This results in using half the needed texture memory +of 16bit texture and can improve performance. This is very little difference +in visual quality due to the fact that the textures are 8bit sources to +begin with. + +run time options +---------------- +At the console, you can set these values to effect drawing. + +gl_texturemode GL_NEAREST +Sets texture mapping to point sampled, which may be faster on some GL systems +(not on 3dfx). + +gl_texturemode GL_LINEAR_MIPMAP +This is the default texture mode. + +gl_texturemode GL_LINEAR_MIPMAP_LINEAR +This is the highest quality texture mapping (trilinear), but only very high +end hardware (intergraph intense 3D / realizm) supports it. Not that big of +a deal, actually. + +gl_finish 0 +This causes the game to not issue a glFinish() call each frame, which may make +some hardware run faster. If this is cleared, the 3dfx will back up a number +of frames and not be very playable. + +gl_flashblend 0 +By default, glquake just draws a shaded ball around objects that are emiting +light. Clearing this variable will cause it to properly relight the world +like normal quake, but it can be a significant speed hit on some systems. + +gl_ztrick 0 +Glquake uses a buffering method that avoids clearing the Z buffer, but some +hardware platforms don't like it. If the status bar and console are flashing +every other frame, clear this variable. + +gl_keeptjunctions 0 +If you clear this, glquake will remove colinear vertexes when it reloads the +level. This can give a few percent speedup, but it can leave a couple stray +blinking pixels on the screen. + +novelty features +---------------- +These are some rendering tricks that were easy to do in glquake. They aren't +very robust, but they are pretty cool to look at. + +r_shadows 1 +This causes every object to cast a shadow. + +r_wateralpha 0.7 +This sets the opacity of water textures, so you can see through it in properly +processed maps. 0.3 is very faint, almost like fog. 1 is completely solid +(the default). Unfortunately, the standard quake maps don't contain any +visibility information for seeing past water surfaces, so you can't just play +quake with this turned on. If you just want to see what it looks like, you +can set "r_novis 1", but that will make things go very slow. When I get a +chance, I will probably release some maps that have been processed properly +for this. + +r_mirroralpha 0.3 +This changes one particular texture (the stained glass texture in the EASY +start hall) into a mirror. The value is the opacity of the mirror surface. + diff --git a/WinQuake/glquake.h b/WinQuake/glquake.h index f3c253c..45bdfff 100644 --- a/WinQuake/glquake.h +++ b/WinQuake/glquake.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // disable data conversion warnings #pragma warning(disable : 4244) // MIPS diff --git a/WinQuake/glquake2.h b/WinQuake/glquake2.h index 06ea6f7..877f546 100644 --- a/WinQuake/glquake2.h +++ b/WinQuake/glquake2.h @@ -1,209 +1,209 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// disable data conversion warnings - -#pragma warning(disable : 4244) // MIPS -#pragma warning(disable : 4136) // X86 -#pragma warning(disable : 4051) // ALPHA - -#include - -#include -#include - -void GL_BeginRendering (int *x, int *y, int *width, int *height); -void GL_EndRendering (void); - - -// Function prototypes for the Texture Object Extension routines -typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *, - const GLboolean *); -typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint); -typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *); -typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *); -typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint); -typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *, - const GLclampf *); -typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *); - -extern BINDTEXFUNCPTR bindTexFunc; -extern DELTEXFUNCPTR delTexFunc; -extern TEXSUBIMAGEPTR TexSubImage2DFunc; - -extern int texture_extension_number; -extern int texture_mode; - -extern float gldepthmin, gldepthmax; - -void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate); -void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate); -int GL_LoadTexture (char *identifier, int width, int height, byte *data, int mipmap, int alpha, int modulate); -int GL_FindTexture (char *identifier); - -typedef struct -{ - float x, y, z; - float s, t; - float r, g, b; -} glvert_t; - -extern glvert_t glv; - -extern int glx, gly, glwidth, glheight; - -extern PROC glArrayElementEXT; -extern PROC glColorPointerEXT; -extern PROC glTexturePointerEXT; -extern PROC glVertexPointerEXT; - - -// r_local.h -- private refresh defs - -#define MAXALIASVERTS 2000 // TODO: tune this - -#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) - // normalizing factor so player model works out to about - // 1 pixel per triangle -#define MAX_LBM_HEIGHT 480 - -#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf - -#define SKYSHIFT 7 -#define SKYSIZE (1 << SKYSHIFT) -#define SKYMASK (SKYSIZE - 1) - -#define BACKFACE_EPSILON 0.01 - - -void R_TimeRefresh_f (void); -void R_ReadPointFile_f (void); -texture_t *R_TextureAnimation (texture_t *base); - -typedef struct surfcache_s -{ - struct surfcache_s *next; - struct surfcache_s **owner; // NULL is an empty chunk of memory - int lightadj[MAXLIGHTMAPS]; // checked for strobe flush - int dlight; - int size; // including header - unsigned width; - unsigned height; // DEBUG only needed for debug - float mipscale; - struct texture_s *texture; // checked for animating textures - byte data[4]; // width*height elements -} surfcache_t; - - -typedef struct -{ - pixel_t *surfdat; // destination for generated surface - int rowbytes; // destination logical width in bytes - msurface_t *surf; // description for surface to generate - fixed8_t lightadj[MAXLIGHTMAPS]; - // adjust for lightmap levels for dynamic lighting - texture_t *texture; // corrected for animating textures - int surfmip; // mipmapped ratio of surface texels / world pixels - int surfwidth; // in mipmapped texels - int surfheight; // in mipmapped texels -} drawsurf_t; - - -typedef enum { - pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2 -} ptype_t; - -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -typedef struct particle_s -{ -// driver-usable fields - vec3_t org; - float color; -// drivers never touch the following fields - struct particle_s *next; - vec3_t vel; - float ramp; - float die; - ptype_t type; -} particle_t; - - -//==================================================== - - -extern entity_t r_worldentity; -extern qboolean r_cache_thrash; // compatability -extern vec3_t modelorg, r_entorigin; -extern entity_t *currententity; -extern int r_visframecount; // ??? what difs? -extern int r_framecount; -extern mplane_t frustum[4]; -extern int c_brush_polys, c_alias_polys; - - -// -// view origin -// -extern vec3_t vup; -extern vec3_t vpn; -extern vec3_t vright; -extern vec3_t r_origin; - -// -// screen size info -// -extern refdef_t r_refdef; -extern mleaf_t *r_viewleaf, *r_oldviewleaf; -extern texture_t *r_notexture_mip; -extern int d_lightstylevalue[256]; // 8.8 fraction of base light value - -extern qboolean envmap; -extern int currenttexture; -extern int particletexture; -extern int playertextures; - -extern int skytexturenum; // index in cl.loadmodel, not gl texture object - -extern cvar_t r_drawentities; -extern cvar_t r_drawworld; -extern cvar_t r_drawviewmodel; -extern cvar_t r_speeds; -extern cvar_t r_waterwarp; -extern cvar_t r_fullbright; -extern cvar_t r_lightmap; -extern cvar_t r_shadows; -extern cvar_t r_dynamic; - -extern cvar_t gl_clear; -extern cvar_t gl_cull; -extern cvar_t gl_poly; -extern cvar_t gl_texsort; -extern cvar_t gl_smoothmodels; -extern cvar_t gl_affinemodels; -extern cvar_t gl_fogblend; -extern cvar_t gl_polyblend; -extern cvar_t gl_keeptjunctions; -extern cvar_t gl_reporttjunctions; - -extern int gl_lightmap_format; -extern int gl_solid_format; -extern int gl_alpha_format; - -void R_TranslatePlayerSkin (int playernum); -void GL_Bind (int texnum); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// disable data conversion warnings + +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#include + +#include +#include + +void GL_BeginRendering (int *x, int *y, int *width, int *height); +void GL_EndRendering (void); + + +// Function prototypes for the Texture Object Extension routines +typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *, + const GLboolean *); +typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint); +typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *); +typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *); +typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint); +typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *, + const GLclampf *); +typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *); + +extern BINDTEXFUNCPTR bindTexFunc; +extern DELTEXFUNCPTR delTexFunc; +extern TEXSUBIMAGEPTR TexSubImage2DFunc; + +extern int texture_extension_number; +extern int texture_mode; + +extern float gldepthmin, gldepthmax; + +void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate); +void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean modulate); +int GL_LoadTexture (char *identifier, int width, int height, byte *data, int mipmap, int alpha, int modulate); +int GL_FindTexture (char *identifier); + +typedef struct +{ + float x, y, z; + float s, t; + float r, g, b; +} glvert_t; + +extern glvert_t glv; + +extern int glx, gly, glwidth, glheight; + +extern PROC glArrayElementEXT; +extern PROC glColorPointerEXT; +extern PROC glTexturePointerEXT; +extern PROC glVertexPointerEXT; + + +// r_local.h -- private refresh defs + +#define MAXALIASVERTS 2000 // TODO: tune this + +#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) + // normalizing factor so player model works out to about + // 1 pixel per triangle +#define MAX_LBM_HEIGHT 480 + +#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf + +#define SKYSHIFT 7 +#define SKYSIZE (1 << SKYSHIFT) +#define SKYMASK (SKYSIZE - 1) + +#define BACKFACE_EPSILON 0.01 + + +void R_TimeRefresh_f (void); +void R_ReadPointFile_f (void); +texture_t *R_TextureAnimation (texture_t *base); + +typedef struct surfcache_s +{ + struct surfcache_s *next; + struct surfcache_s **owner; // NULL is an empty chunk of memory + int lightadj[MAXLIGHTMAPS]; // checked for strobe flush + int dlight; + int size; // including header + unsigned width; + unsigned height; // DEBUG only needed for debug + float mipscale; + struct texture_s *texture; // checked for animating textures + byte data[4]; // width*height elements +} surfcache_t; + + +typedef struct +{ + pixel_t *surfdat; // destination for generated surface + int rowbytes; // destination logical width in bytes + msurface_t *surf; // description for surface to generate + fixed8_t lightadj[MAXLIGHTMAPS]; + // adjust for lightmap levels for dynamic lighting + texture_t *texture; // corrected for animating textures + int surfmip; // mipmapped ratio of surface texels / world pixels + int surfwidth; // in mipmapped texels + int surfheight; // in mipmapped texels +} drawsurf_t; + + +typedef enum { + pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2 +} ptype_t; + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +typedef struct particle_s +{ +// driver-usable fields + vec3_t org; + float color; +// drivers never touch the following fields + struct particle_s *next; + vec3_t vel; + float ramp; + float die; + ptype_t type; +} particle_t; + + +//==================================================== + + +extern entity_t r_worldentity; +extern qboolean r_cache_thrash; // compatability +extern vec3_t modelorg, r_entorigin; +extern entity_t *currententity; +extern int r_visframecount; // ??? what difs? +extern int r_framecount; +extern mplane_t frustum[4]; +extern int c_brush_polys, c_alias_polys; + + +// +// view origin +// +extern vec3_t vup; +extern vec3_t vpn; +extern vec3_t vright; +extern vec3_t r_origin; + +// +// screen size info +// +extern refdef_t r_refdef; +extern mleaf_t *r_viewleaf, *r_oldviewleaf; +extern texture_t *r_notexture_mip; +extern int d_lightstylevalue[256]; // 8.8 fraction of base light value + +extern qboolean envmap; +extern int currenttexture; +extern int particletexture; +extern int playertextures; + +extern int skytexturenum; // index in cl.loadmodel, not gl texture object + +extern cvar_t r_drawentities; +extern cvar_t r_drawworld; +extern cvar_t r_drawviewmodel; +extern cvar_t r_speeds; +extern cvar_t r_waterwarp; +extern cvar_t r_fullbright; +extern cvar_t r_lightmap; +extern cvar_t r_shadows; +extern cvar_t r_dynamic; + +extern cvar_t gl_clear; +extern cvar_t gl_cull; +extern cvar_t gl_poly; +extern cvar_t gl_texsort; +extern cvar_t gl_smoothmodels; +extern cvar_t gl_affinemodels; +extern cvar_t gl_fogblend; +extern cvar_t gl_polyblend; +extern cvar_t gl_keeptjunctions; +extern cvar_t gl_reporttjunctions; + +extern int gl_lightmap_format; +extern int gl_solid_format; +extern int gl_alpha_format; + +void R_TranslatePlayerSkin (int playernum); +void GL_Bind (int texnum); diff --git a/WinQuake/host.c b/WinQuake/host.c index 603f6b3..9772d6d 100644 --- a/WinQuake/host.c +++ b/WinQuake/host.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // host.c -- coordinates spawning and killing of local servers #include "quakedef.h" diff --git a/WinQuake/host_cmd.c b/WinQuake/host_cmd.c index e658cd4..073feaa 100644 --- a/WinQuake/host_cmd.c +++ b/WinQuake/host_cmd.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #include "quakedef.h" diff --git a/WinQuake/in_dos.c b/WinQuake/in_dos.c index fab89f4..4aa03ac 100644 --- a/WinQuake/in_dos.c +++ b/WinQuake/in_dos.c @@ -1,615 +1,615 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// in_mouse.c -- dos mouse code - -#include "quakedef.h" -#include "dosisms.h" - -#define AUX_FLAG_FREELOOK 0x00000001 - -typedef struct -{ - long interruptVector; - char deviceName[16]; - long numAxes; - long numButtons; - long flags; - - vec3_t viewangles; - -// intended velocities - float forwardmove; - float sidemove; - float upmove; - - long buttons; -} externControl_t; - -/* -#define AUX_FLAG_FORCEFREELOOK 0x00000001 // r/o -#define AUX_FLAG_EXTENDED 0x00000002 // r/o -#define AUX_FLAG_RUN 0x00000004 // w/o -#define AUX_FLAG_STRAFE 0x00000008 // w/o -#define AUX_FLAG_FREELOOK 0x00000010 // w/o - -#define AUX_MAP_UNDEFINED 0 -#define AUX_MAP_PITCH 1 -#define AUX_MAP_YAW 2 -#define AUX_MAP_ROLL 3 -#define AUX_MAP_FORWARD 4 -#define AUX_MAP_SIDE 5 -#define AUX_MAP_UP 6 - -typedef struct -{ - long interruptVector; - // r/o - char deviceName[16]; - // r/o - long numAxes; - // r/o 1-6 - long numButtons; // r/o 0-32 - long flags; // see above - byte axisMapping[6]; // w/o default = p,y,r,f,s,u - float axisValue[6]; // r/w - float sensitivity[6]; // w/o default = 1.0 - long buttons; // r/o - float last_frame_time; // w/o -} externControl_t; -*/ - -cvar_t m_filter = {"m_filter","1"}; - -qboolean mouse_avail; -int mouse_buttons; -int mouse_oldbuttonstate; -int mouse_buttonstate; -float mouse_x, mouse_y; -float old_mouse_x, old_mouse_y; - - -cvar_t in_joystick = {"joystick","1"}; -cvar_t joy_numbuttons = {"joybuttons","4", true}; - -qboolean joy_avail; -int joy_oldbuttonstate; -int joy_buttonstate; - -int joyxl, joyxh, joyyl, joyyh; -int joystickx, joysticky; - -qboolean need_center; - -qboolean extern_avail; -int extern_buttons; -int extern_oldbuttonstate; -int extern_buttonstate; -cvar_t aux_look = {"auxlook","1", true}; -externControl_t *extern_control; -void IN_StartupExternal (void); -void IN_ExternalMove (usercmd_t *cmd); - -void IN_StartupJoystick (void); -qboolean IN_ReadJoystick (void); - - -void Toggle_AuxLook_f (void) -{ - if (aux_look.value) - Cvar_Set ("auxlook","0"); - else - Cvar_Set ("auxlook","1"); -} - - -void Force_CenterView_f (void) -{ - cl.viewangles[PITCH] = 0; -} - - -/* -=========== -IN_StartupMouse -=========== -*/ -void IN_StartupMouse (void) -{ - if ( COM_CheckParm ("-nomouse") ) - return; - -// check for mouse - regs.x.ax = 0; - dos_int86(0x33); - mouse_avail = regs.x.ax; - if (!mouse_avail) - { - Con_Printf ("No mouse found\n"); - return; - } - - mouse_buttons = regs.x.bx; - if (mouse_buttons > 3) - mouse_buttons = 3; - Con_Printf("%d-button mouse available\n", mouse_buttons); -} - -/* -=========== -IN_Init -=========== -*/ -void IN_Init (void) -{ - int i; - - Cvar_RegisterVariable (&m_filter); - Cvar_RegisterVariable (&in_joystick); - Cvar_RegisterVariable (&joy_numbuttons); - Cvar_RegisterVariable (&aux_look); - Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f); - Cmd_AddCommand ("force_centerview", Force_CenterView_f); - - IN_StartupMouse (); - IN_StartupJoystick (); - - i = COM_CheckParm ("-control"); - if (i) - { - extern_control = real2ptr(Q_atoi (com_argv[i+1])); - IN_StartupExternal (); - } -} - -/* -=========== -IN_Shutdown -=========== -*/ -void IN_Shutdown (void) -{ - -} - - -/* -=========== -IN_Commands -=========== -*/ -void IN_Commands (void) -{ - int i; - - if (mouse_avail) - { - regs.x.ax = 3; // read buttons - dos_int86(0x33); - mouse_buttonstate = regs.x.bx; - - // perform button actions - for (i=0 ; i> 4)&15)^15; - // perform button actions - for (i=0 ; ibuttons; - - // perform button actions - for (i=0 ; isidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) - { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } - else - { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } -} - -/* -=========== -IN_JoyMove -=========== -*/ -void IN_JoyMove (usercmd_t *cmd) -{ - float speed, aspeed; - - if (!joy_avail || !in_joystick.value) - return; - - IN_ReadJoystick (); - if (joysticky > joyyh*2 || joystickx > joyxh*2) - return; // assume something jumped in and messed up the joystick - // reading time (win 95) - - if (in_speed.state & 1) - speed = cl_movespeedkey.value; - else - speed = 1; - aspeed = speed*host_frametime; - - if (in_strafe.state & 1) - { - if (joystickx < joyxl) - cmd->sidemove -= speed*cl_sidespeed.value; - else if (joystickx > joyxh) - cmd->sidemove += speed*cl_sidespeed.value; - } - else - { - if (joystickx < joyxl) - cl.viewangles[YAW] += aspeed*cl_yawspeed.value; - else if (joystickx > joyxh) - cl.viewangles[YAW] -= aspeed*cl_yawspeed.value; - cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); - } - - if (in_mlook.state & 1) - { - if (m_pitch.value < 0) - speed *= -1; - - if (joysticky < joyyl) - cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value; - else if (joysticky > joyyh) - cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value; - } - else - { - if (joysticky < joyyl) - cmd->forwardmove += speed*cl_forwardspeed.value; - else if (joysticky > joyyh) - cmd->forwardmove -= speed*cl_backspeed.value; - } -} - -/* -=========== -IN_Move -=========== -*/ -void IN_Move (usercmd_t *cmd) -{ - IN_MouseMove (cmd); - IN_JoyMove (cmd); - IN_ExternalMove (cmd); -} - -/* -============================================================================ - - JOYSTICK - -============================================================================ -*/ - - - -qboolean IN_ReadJoystick (void) -{ - int b; - int count; - - joystickx = 0; - joysticky = 0; - - count = 0; - - b = dos_inportb(0x201); - dos_outportb(0x201, b); - -// clear counters - while (++count < 10000) - { - b = dos_inportb(0x201); - - joystickx += b&1; - joysticky += (b&2)>>1; - if ( !(b&3) ) - return true; - } - - Con_Printf ("IN_ReadJoystick: no response\n"); - joy_avail = false; - return false; -} - -/* -============= -WaitJoyButton -============= -*/ -qboolean WaitJoyButton (void) -{ - int oldbuttons, buttons; - - oldbuttons = 0; - do - { - key_count = -1; - Sys_SendKeyEvents (); - key_count = 0; - if (key_lastpress == K_ESCAPE) - { - Con_Printf ("aborted.\n"); - return false; - } - key_lastpress = 0; - SCR_UpdateScreen (); - buttons = ((dos_inportb(0x201) >> 4)&1)^1; - if (buttons != oldbuttons) - { - oldbuttons = buttons; - continue; - } - } while ( !buttons); - - do - { - key_count = -1; - Sys_SendKeyEvents (); - key_count = 0; - if (key_lastpress == K_ESCAPE) - { - Con_Printf ("aborted.\n"); - return false; - } - key_lastpress = 0; - SCR_UpdateScreen (); - buttons = ((dos_inportb(0x201) >> 4)&1)^1; - if (buttons != oldbuttons) - { - oldbuttons = buttons; - continue; - } - } while ( buttons); - - return true; -} - - - -/* -=============== -IN_StartupJoystick -=============== -*/ -void IN_StartupJoystick (void) -{ - int centerx, centery; - - Con_Printf ("\n"); - - joy_avail = false; - if ( COM_CheckParm ("-nojoy") ) - return; - - if (!IN_ReadJoystick ()) - { - joy_avail = false; - Con_Printf ("joystick not found\n"); - return; - } - - Con_Printf ("joystick found\n"); - - Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n"); - if (!WaitJoyButton ()) - return; - IN_ReadJoystick (); - centerx = joystickx; - centery = joysticky; - - Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n"); - if (!WaitJoyButton ()) - return; - IN_ReadJoystick (); - joyxl = (centerx + joystickx)/2; - joyyl = (centerx + joysticky)/2; - - Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n"); - if (!WaitJoyButton ()) - return; - IN_ReadJoystick (); - joyxh = (centerx + joystickx)/2; - joyyh = (centery + joysticky)/2; - - joy_avail = true; - Con_Printf ("joystick configured.\n"); - - Con_Printf ("\n"); -} - - -/* -============================================================================ - - EXTERNAL - -============================================================================ -*/ - - -/* -=============== -IN_StartupExternal -=============== -*/ -void IN_StartupExternal (void) -{ - if (extern_control->numButtons > 32) - extern_control->numButtons = 32; - - Con_Printf("%s Initialized\n", extern_control->deviceName); - Con_Printf(" %u axes %u buttons\n", extern_control->numAxes, extern_control->numButtons); - - extern_avail = true; - extern_buttons = extern_control->numButtons; -} - - -/* -=========== -IN_ExternalMove -=========== -*/ -void IN_ExternalMove (usercmd_t *cmd) -{ - qboolean freelook; - - if (! extern_avail) - return; - - extern_control->viewangles[YAW] = cl.viewangles[YAW]; - extern_control->viewangles[PITCH] = cl.viewangles[PITCH]; - extern_control->viewangles[ROLL] = cl.viewangles[ROLL]; - extern_control->forwardmove = cmd->forwardmove; - extern_control->sidemove = cmd->sidemove; - extern_control->upmove = cmd->upmove; - -Con_DPrintf("IN: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove); - - dos_int86(extern_control->interruptVector); - -Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove); - - cl.viewangles[YAW] = extern_control->viewangles[YAW]; - cl.viewangles[PITCH] = extern_control->viewangles[PITCH]; - cl.viewangles[ROLL] = extern_control->viewangles[ROLL]; - cmd->forwardmove = extern_control->forwardmove; - cmd->sidemove = extern_control->sidemove; - cmd->upmove = extern_control->upmove; - - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - - freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1); - - if (freelook) - V_StopPitchDrift (); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// in_mouse.c -- dos mouse code + +#include "quakedef.h" +#include "dosisms.h" + +#define AUX_FLAG_FREELOOK 0x00000001 + +typedef struct +{ + long interruptVector; + char deviceName[16]; + long numAxes; + long numButtons; + long flags; + + vec3_t viewangles; + +// intended velocities + float forwardmove; + float sidemove; + float upmove; + + long buttons; +} externControl_t; + +/* +#define AUX_FLAG_FORCEFREELOOK 0x00000001 // r/o +#define AUX_FLAG_EXTENDED 0x00000002 // r/o +#define AUX_FLAG_RUN 0x00000004 // w/o +#define AUX_FLAG_STRAFE 0x00000008 // w/o +#define AUX_FLAG_FREELOOK 0x00000010 // w/o + +#define AUX_MAP_UNDEFINED 0 +#define AUX_MAP_PITCH 1 +#define AUX_MAP_YAW 2 +#define AUX_MAP_ROLL 3 +#define AUX_MAP_FORWARD 4 +#define AUX_MAP_SIDE 5 +#define AUX_MAP_UP 6 + +typedef struct +{ + long interruptVector; + // r/o + char deviceName[16]; + // r/o + long numAxes; + // r/o 1-6 + long numButtons; // r/o 0-32 + long flags; // see above + byte axisMapping[6]; // w/o default = p,y,r,f,s,u + float axisValue[6]; // r/w + float sensitivity[6]; // w/o default = 1.0 + long buttons; // r/o + float last_frame_time; // w/o +} externControl_t; +*/ + +cvar_t m_filter = {"m_filter","1"}; + +qboolean mouse_avail; +int mouse_buttons; +int mouse_oldbuttonstate; +int mouse_buttonstate; +float mouse_x, mouse_y; +float old_mouse_x, old_mouse_y; + + +cvar_t in_joystick = {"joystick","1"}; +cvar_t joy_numbuttons = {"joybuttons","4", true}; + +qboolean joy_avail; +int joy_oldbuttonstate; +int joy_buttonstate; + +int joyxl, joyxh, joyyl, joyyh; +int joystickx, joysticky; + +qboolean need_center; + +qboolean extern_avail; +int extern_buttons; +int extern_oldbuttonstate; +int extern_buttonstate; +cvar_t aux_look = {"auxlook","1", true}; +externControl_t *extern_control; +void IN_StartupExternal (void); +void IN_ExternalMove (usercmd_t *cmd); + +void IN_StartupJoystick (void); +qboolean IN_ReadJoystick (void); + + +void Toggle_AuxLook_f (void) +{ + if (aux_look.value) + Cvar_Set ("auxlook","0"); + else + Cvar_Set ("auxlook","1"); +} + + +void Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + + +/* +=========== +IN_StartupMouse +=========== +*/ +void IN_StartupMouse (void) +{ + if ( COM_CheckParm ("-nomouse") ) + return; + +// check for mouse + regs.x.ax = 0; + dos_int86(0x33); + mouse_avail = regs.x.ax; + if (!mouse_avail) + { + Con_Printf ("No mouse found\n"); + return; + } + + mouse_buttons = regs.x.bx; + if (mouse_buttons > 3) + mouse_buttons = 3; + Con_Printf("%d-button mouse available\n", mouse_buttons); +} + +/* +=========== +IN_Init +=========== +*/ +void IN_Init (void) +{ + int i; + + Cvar_RegisterVariable (&m_filter); + Cvar_RegisterVariable (&in_joystick); + Cvar_RegisterVariable (&joy_numbuttons); + Cvar_RegisterVariable (&aux_look); + Cmd_AddCommand ("toggle_auxlook", Toggle_AuxLook_f); + Cmd_AddCommand ("force_centerview", Force_CenterView_f); + + IN_StartupMouse (); + IN_StartupJoystick (); + + i = COM_CheckParm ("-control"); + if (i) + { + extern_control = real2ptr(Q_atoi (com_argv[i+1])); + IN_StartupExternal (); + } +} + +/* +=========== +IN_Shutdown +=========== +*/ +void IN_Shutdown (void) +{ + +} + + +/* +=========== +IN_Commands +=========== +*/ +void IN_Commands (void) +{ + int i; + + if (mouse_avail) + { + regs.x.ax = 3; // read buttons + dos_int86(0x33); + mouse_buttonstate = regs.x.bx; + + // perform button actions + for (i=0 ; i> 4)&15)^15; + // perform button actions + for (i=0 ; ibuttons; + + // perform button actions + for (i=0 ; isidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } +} + +/* +=========== +IN_JoyMove +=========== +*/ +void IN_JoyMove (usercmd_t *cmd) +{ + float speed, aspeed; + + if (!joy_avail || !in_joystick.value) + return; + + IN_ReadJoystick (); + if (joysticky > joyyh*2 || joystickx > joyxh*2) + return; // assume something jumped in and messed up the joystick + // reading time (win 95) + + if (in_speed.state & 1) + speed = cl_movespeedkey.value; + else + speed = 1; + aspeed = speed*host_frametime; + + if (in_strafe.state & 1) + { + if (joystickx < joyxl) + cmd->sidemove -= speed*cl_sidespeed.value; + else if (joystickx > joyxh) + cmd->sidemove += speed*cl_sidespeed.value; + } + else + { + if (joystickx < joyxl) + cl.viewangles[YAW] += aspeed*cl_yawspeed.value; + else if (joystickx > joyxh) + cl.viewangles[YAW] -= aspeed*cl_yawspeed.value; + cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); + } + + if (in_mlook.state & 1) + { + if (m_pitch.value < 0) + speed *= -1; + + if (joysticky < joyyl) + cl.viewangles[PITCH] += aspeed*cl_pitchspeed.value; + else if (joysticky > joyyh) + cl.viewangles[PITCH] -= aspeed*cl_pitchspeed.value; + } + else + { + if (joysticky < joyyl) + cmd->forwardmove += speed*cl_forwardspeed.value; + else if (joysticky > joyyh) + cmd->forwardmove -= speed*cl_backspeed.value; + } +} + +/* +=========== +IN_Move +=========== +*/ +void IN_Move (usercmd_t *cmd) +{ + IN_MouseMove (cmd); + IN_JoyMove (cmd); + IN_ExternalMove (cmd); +} + +/* +============================================================================ + + JOYSTICK + +============================================================================ +*/ + + + +qboolean IN_ReadJoystick (void) +{ + int b; + int count; + + joystickx = 0; + joysticky = 0; + + count = 0; + + b = dos_inportb(0x201); + dos_outportb(0x201, b); + +// clear counters + while (++count < 10000) + { + b = dos_inportb(0x201); + + joystickx += b&1; + joysticky += (b&2)>>1; + if ( !(b&3) ) + return true; + } + + Con_Printf ("IN_ReadJoystick: no response\n"); + joy_avail = false; + return false; +} + +/* +============= +WaitJoyButton +============= +*/ +qboolean WaitJoyButton (void) +{ + int oldbuttons, buttons; + + oldbuttons = 0; + do + { + key_count = -1; + Sys_SendKeyEvents (); + key_count = 0; + if (key_lastpress == K_ESCAPE) + { + Con_Printf ("aborted.\n"); + return false; + } + key_lastpress = 0; + SCR_UpdateScreen (); + buttons = ((dos_inportb(0x201) >> 4)&1)^1; + if (buttons != oldbuttons) + { + oldbuttons = buttons; + continue; + } + } while ( !buttons); + + do + { + key_count = -1; + Sys_SendKeyEvents (); + key_count = 0; + if (key_lastpress == K_ESCAPE) + { + Con_Printf ("aborted.\n"); + return false; + } + key_lastpress = 0; + SCR_UpdateScreen (); + buttons = ((dos_inportb(0x201) >> 4)&1)^1; + if (buttons != oldbuttons) + { + oldbuttons = buttons; + continue; + } + } while ( buttons); + + return true; +} + + + +/* +=============== +IN_StartupJoystick +=============== +*/ +void IN_StartupJoystick (void) +{ + int centerx, centery; + + Con_Printf ("\n"); + + joy_avail = false; + if ( COM_CheckParm ("-nojoy") ) + return; + + if (!IN_ReadJoystick ()) + { + joy_avail = false; + Con_Printf ("joystick not found\n"); + return; + } + + Con_Printf ("joystick found\n"); + + Con_Printf ("CENTER the joystick\nand press button 1 (ESC to skip):\n"); + if (!WaitJoyButton ()) + return; + IN_ReadJoystick (); + centerx = joystickx; + centery = joysticky; + + Con_Printf ("Push the joystick to the UPPER LEFT\nand press button 1 (ESC to skip):\n"); + if (!WaitJoyButton ()) + return; + IN_ReadJoystick (); + joyxl = (centerx + joystickx)/2; + joyyl = (centerx + joysticky)/2; + + Con_Printf ("Push the joystick to the LOWER RIGHT\nand press button 1 (ESC to skip):\n"); + if (!WaitJoyButton ()) + return; + IN_ReadJoystick (); + joyxh = (centerx + joystickx)/2; + joyyh = (centery + joysticky)/2; + + joy_avail = true; + Con_Printf ("joystick configured.\n"); + + Con_Printf ("\n"); +} + + +/* +============================================================================ + + EXTERNAL + +============================================================================ +*/ + + +/* +=============== +IN_StartupExternal +=============== +*/ +void IN_StartupExternal (void) +{ + if (extern_control->numButtons > 32) + extern_control->numButtons = 32; + + Con_Printf("%s Initialized\n", extern_control->deviceName); + Con_Printf(" %u axes %u buttons\n", extern_control->numAxes, extern_control->numButtons); + + extern_avail = true; + extern_buttons = extern_control->numButtons; +} + + +/* +=========== +IN_ExternalMove +=========== +*/ +void IN_ExternalMove (usercmd_t *cmd) +{ + qboolean freelook; + + if (! extern_avail) + return; + + extern_control->viewangles[YAW] = cl.viewangles[YAW]; + extern_control->viewangles[PITCH] = cl.viewangles[PITCH]; + extern_control->viewangles[ROLL] = cl.viewangles[ROLL]; + extern_control->forwardmove = cmd->forwardmove; + extern_control->sidemove = cmd->sidemove; + extern_control->upmove = cmd->upmove; + +Con_DPrintf("IN: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove); + + dos_int86(extern_control->interruptVector); + +Con_DPrintf("OUT: y:%f p:%f r:%f f:%f s:%f u:%f\n", extern_control->viewangles[YAW], extern_control->viewangles[PITCH], extern_control->viewangles[ROLL], extern_control->forwardmove, extern_control->sidemove, extern_control->upmove); + + cl.viewangles[YAW] = extern_control->viewangles[YAW]; + cl.viewangles[PITCH] = extern_control->viewangles[PITCH]; + cl.viewangles[ROLL] = extern_control->viewangles[ROLL]; + cmd->forwardmove = extern_control->forwardmove; + cmd->sidemove = extern_control->sidemove; + cmd->upmove = extern_control->upmove; + + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + + freelook = (extern_control->flags & AUX_FLAG_FREELOOK || aux_look.value || in_mlook.state & 1); + + if (freelook) + V_StopPitchDrift (); +} + diff --git a/WinQuake/in_null.c b/WinQuake/in_null.c index 1c54ee4..1c0662c 100644 --- a/WinQuake/in_null.c +++ b/WinQuake/in_null.c @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// in_null.c -- for systems without a mouse - -#include "quakedef.h" - -void IN_Init (void) -{ -} - -void IN_Shutdown (void) -{ -} - -void IN_Commands (void) -{ -} - -void IN_Move (usercmd_t *cmd) -{ -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// in_null.c -- for systems without a mouse + +#include "quakedef.h" + +void IN_Init (void) +{ +} + +void IN_Shutdown (void) +{ +} + +void IN_Commands (void) +{ +} + +void IN_Move (usercmd_t *cmd) +{ +} + diff --git a/WinQuake/in_sun.c b/WinQuake/in_sun.c index 3ffede5..246ea2e 100644 --- a/WinQuake/in_sun.c +++ b/WinQuake/in_sun.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // in_sun.c -- SUN/X mouse input handler #include diff --git a/WinQuake/in_win.c b/WinQuake/in_win.c index d8544fb..f066ec2 100644 --- a/WinQuake/in_win.c +++ b/WinQuake/in_win.c @@ -1,1239 +1,1239 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// in_win.c -- windows 95 mouse and joystick code -// 02/21/97 JCB Added extended DirectInput code to support external controllers. - -#include -#include "quakedef.h" -#include "winquake.h" -#include "dosisms.h" - -#define DINPUT_BUFFERSIZE 16 -#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) - -HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, - LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); - -// mouse variables -cvar_t m_filter = {"m_filter","0"}; - -int mouse_buttons; -int mouse_oldbuttonstate; -POINT current_pos; -int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; - -static qboolean restore_spi; -static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; - -unsigned int uiWheelMessage; -qboolean mouseactive; -qboolean mouseinitialized; -static qboolean mouseparmsvalid, mouseactivatetoggle; -static qboolean mouseshowtoggle = 1; -static qboolean dinput_acquired; - -static unsigned int mstate_di; - -// joystick defines and variables -// where should defines be moved? -#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick -#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball -#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V -#define JOY_AXIS_X 0 -#define JOY_AXIS_Y 1 -#define JOY_AXIS_Z 2 -#define JOY_AXIS_R 3 -#define JOY_AXIS_U 4 -#define JOY_AXIS_V 5 - -enum _ControlList -{ - AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn -}; - -DWORD dwAxisFlags[JOY_MAX_AXES] = -{ - JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV -}; - -DWORD dwAxisMap[JOY_MAX_AXES]; -DWORD dwControlMap[JOY_MAX_AXES]; -PDWORD pdwRawValue[JOY_MAX_AXES]; - -// none of these cvars are saved over a session -// this means that advanced controller configuration needs to be executed -// each time. this avoids any problems with getting back to a default usage -// or when changing from one controller to another. this way at least something -// works. -cvar_t in_joystick = {"joystick","0", true}; -cvar_t joy_name = {"joyname", "joystick"}; -cvar_t joy_advanced = {"joyadvanced", "0"}; -cvar_t joy_advaxisx = {"joyadvaxisx", "0"}; -cvar_t joy_advaxisy = {"joyadvaxisy", "0"}; -cvar_t joy_advaxisz = {"joyadvaxisz", "0"}; -cvar_t joy_advaxisr = {"joyadvaxisr", "0"}; -cvar_t joy_advaxisu = {"joyadvaxisu", "0"}; -cvar_t joy_advaxisv = {"joyadvaxisv", "0"}; -cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"}; -cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"}; -cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"}; -cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"}; -cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"}; -cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"}; -cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"}; -cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"}; -cvar_t joy_wwhack1 = {"joywwhack1", "0.0"}; -cvar_t joy_wwhack2 = {"joywwhack2", "0.0"}; - -qboolean joy_avail, joy_advancedinit, joy_haspov; -DWORD joy_oldbuttonstate, joy_oldpovstate; - -int joy_id; -DWORD joy_flags; -DWORD joy_numbuttons; - -static LPDIRECTINPUT g_pdi; -static LPDIRECTINPUTDEVICE g_pMouse; - -static JOYINFOEX ji; - -static HINSTANCE hInstDI; - -static qboolean dinput; - -typedef struct MYDATA { - LONG lX; // X axis goes here - LONG lY; // Y axis goes here - LONG lZ; // Z axis goes here - BYTE bButtonA; // One button goes here - BYTE bButtonB; // Another button goes here - BYTE bButtonC; // Another button goes here - BYTE bButtonD; // Another button goes here -} MYDATA; - -static DIOBJECTDATAFORMAT rgodf[] = { - { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, - { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, -}; - -#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) - -static DIDATAFORMAT df = { - sizeof(DIDATAFORMAT), // this structure - sizeof(DIOBJECTDATAFORMAT), // size of object data format - DIDF_RELAXIS, // absolute axis coordinates - sizeof(MYDATA), // device data size - NUM_OBJECTS, // number of objects - rgodf, // and here they are -}; - -// forward-referenced functions -void IN_StartupJoystick (void); -void Joy_AdvancedUpdate_f (void); -void IN_JoyMove (usercmd_t *cmd); - - -/* -=========== -Force_CenterView_f -=========== -*/ -void Force_CenterView_f (void) -{ - cl.viewangles[PITCH] = 0; -} - - -/* -=========== -IN_UpdateClipCursor -=========== -*/ -void IN_UpdateClipCursor (void) -{ - - if (mouseinitialized && mouseactive && !dinput) - { - ClipCursor (&window_rect); - } -} - - -/* -=========== -IN_ShowMouse -=========== -*/ -void IN_ShowMouse (void) -{ - - if (!mouseshowtoggle) - { - ShowCursor (TRUE); - mouseshowtoggle = 1; - } -} - - -/* -=========== -IN_HideMouse -=========== -*/ -void IN_HideMouse (void) -{ - - if (mouseshowtoggle) - { - ShowCursor (FALSE); - mouseshowtoggle = 0; - } -} - - -/* -=========== -IN_ActivateMouse -=========== -*/ -void IN_ActivateMouse (void) -{ - - mouseactivatetoggle = true; - - if (mouseinitialized) - { - if (dinput) - { - if (g_pMouse) - { - if (!dinput_acquired) - { - IDirectInputDevice_Acquire(g_pMouse); - dinput_acquired = true; - } - } - else - { - return; - } - } - else - { - if (mouseparmsvalid) - restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); - - SetCursorPos (window_center_x, window_center_y); - SetCapture (mainwindow); - ClipCursor (&window_rect); - } - - mouseactive = true; - } -} - - -/* -=========== -IN_SetQuakeMouseState -=========== -*/ -void IN_SetQuakeMouseState (void) -{ - if (mouseactivatetoggle) - IN_ActivateMouse (); -} - - -/* -=========== -IN_DeactivateMouse -=========== -*/ -void IN_DeactivateMouse (void) -{ - - mouseactivatetoggle = false; - - if (mouseinitialized) - { - if (dinput) - { - if (g_pMouse) - { - if (dinput_acquired) - { - IDirectInputDevice_Unacquire(g_pMouse); - dinput_acquired = false; - } - } - } - else - { - if (restore_spi) - SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); - - ClipCursor (NULL); - ReleaseCapture (); - } - - mouseactive = false; - } -} - - -/* -=========== -IN_RestoreOriginalMouseState -=========== -*/ -void IN_RestoreOriginalMouseState (void) -{ - if (mouseactivatetoggle) - { - IN_DeactivateMouse (); - mouseactivatetoggle = true; - } - -// try to redraw the cursor so it gets reinitialized, because sometimes it -// has garbage after the mode switch - ShowCursor (TRUE); - ShowCursor (FALSE); -} - - -/* -=========== -IN_InitDInput -=========== -*/ -qboolean IN_InitDInput (void) -{ - HRESULT hr; - DIPROPDWORD dipdw = { - { - sizeof(DIPROPDWORD), // diph.dwSize - sizeof(DIPROPHEADER), // diph.dwHeaderSize - 0, // diph.dwObj - DIPH_DEVICE, // diph.dwHow - }, - DINPUT_BUFFERSIZE, // dwData - }; - - if (!hInstDI) - { - hInstDI = LoadLibrary("dinput.dll"); - - if (hInstDI == NULL) - { - Con_SafePrintf ("Couldn't load dinput.dll\n"); - return false; - } - } - - if (!pDirectInputCreate) - { - pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA"); - - if (!pDirectInputCreate) - { - Con_SafePrintf ("Couldn't get DI proc addr\n"); - return false; - } - } - -// register with DirectInput and get an IDirectInput to play with. - hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); - - if (FAILED(hr)) - { - return false; - } - -// obtain an interface to the system mouse device. - hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't open DI mouse device\n"); - return false; - } - -// set the data format to "mouse format". - hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI mouse format\n"); - return false; - } - -// set the cooperativity level. - hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, - DISCL_EXCLUSIVE | DISCL_FOREGROUND); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI coop level\n"); - return false; - } - - -// set the buffer size to DINPUT_BUFFERSIZE elements. -// the buffer size is a DWORD property associated with the device - hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); - - if (FAILED(hr)) - { - Con_SafePrintf ("Couldn't set DI buffersize\n"); - return false; - } - - return true; -} - - -/* -=========== -IN_StartupMouse -=========== -*/ -void IN_StartupMouse (void) -{ - HDC hdc; - - if ( COM_CheckParm ("-nomouse") ) - return; - - mouseinitialized = true; - - if (COM_CheckParm ("-dinput")) - { - dinput = IN_InitDInput (); - - if (dinput) - { - Con_SafePrintf ("DirectInput initialized\n"); - } - else - { - Con_SafePrintf ("DirectInput not initialized\n"); - } - } - - if (!dinput) - { - mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); - - if (mouseparmsvalid) - { - if ( COM_CheckParm ("-noforcemspd") ) - newmouseparms[2] = originalmouseparms[2]; - - if ( COM_CheckParm ("-noforcemaccel") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - } - - if ( COM_CheckParm ("-noforcemparms") ) - { - newmouseparms[0] = originalmouseparms[0]; - newmouseparms[1] = originalmouseparms[1]; - newmouseparms[2] = originalmouseparms[2]; - } - } - } - - mouse_buttons = 3; - -// if a fullscreen video mode was set before the mouse was initialized, -// set the mouse state appropriately - if (mouseactivatetoggle) - IN_ActivateMouse (); -} - - -/* -=========== -IN_Init -=========== -*/ -void IN_Init (void) -{ - // mouse variables - Cvar_RegisterVariable (&m_filter); - - // joystick variables - Cvar_RegisterVariable (&in_joystick); - Cvar_RegisterVariable (&joy_name); - Cvar_RegisterVariable (&joy_advanced); - Cvar_RegisterVariable (&joy_advaxisx); - Cvar_RegisterVariable (&joy_advaxisy); - Cvar_RegisterVariable (&joy_advaxisz); - Cvar_RegisterVariable (&joy_advaxisr); - Cvar_RegisterVariable (&joy_advaxisu); - Cvar_RegisterVariable (&joy_advaxisv); - Cvar_RegisterVariable (&joy_forwardthreshold); - Cvar_RegisterVariable (&joy_sidethreshold); - Cvar_RegisterVariable (&joy_pitchthreshold); - Cvar_RegisterVariable (&joy_yawthreshold); - Cvar_RegisterVariable (&joy_forwardsensitivity); - Cvar_RegisterVariable (&joy_sidesensitivity); - Cvar_RegisterVariable (&joy_pitchsensitivity); - Cvar_RegisterVariable (&joy_yawsensitivity); - Cvar_RegisterVariable (&joy_wwhack1); - Cvar_RegisterVariable (&joy_wwhack2); - - Cmd_AddCommand ("force_centerview", Force_CenterView_f); - Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); - - uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); - - IN_StartupMouse (); - IN_StartupJoystick (); -} - -/* -=========== -IN_Shutdown -=========== -*/ -void IN_Shutdown (void) -{ - - IN_DeactivateMouse (); - IN_ShowMouse (); - - if (g_pMouse) - { - IDirectInputDevice_Release(g_pMouse); - g_pMouse = NULL; - } - - if (g_pdi) - { - IDirectInput_Release(g_pdi); - g_pdi = NULL; - } -} - - -/* -=========== -IN_MouseEvent -=========== -*/ -void IN_MouseEvent (int mstate) -{ - int i; - - if (mouseactive && !dinput) - { - // perform button actions - for (i=0 ; isidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - - if (in_mlook.state & 1) - V_StopPitchDrift (); - - if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) - { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - } - else - { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } - -// if the mouse has moved, force it to the center, so there's room to move - if (mx || my) - { - SetCursorPos (window_center_x, window_center_y); - } -} - - -/* -=========== -IN_Move -=========== -*/ -void IN_Move (usercmd_t *cmd) -{ - - if (ActiveApp && !Minimized) - { - IN_MouseMove (cmd); - IN_JoyMove (cmd); - } -} - - -/* -=========== -IN_Accumulate -=========== -*/ -void IN_Accumulate (void) -{ - int mx, my; - HDC hdc; - - if (mouseactive) - { - if (!dinput) - { - GetCursorPos (¤t_pos); - - mx_accum += current_pos.x - window_center_x; - my_accum += current_pos.y - window_center_y; - - // force the mouse to the center, so there's room to move - SetCursorPos (window_center_x, window_center_y); - } - } -} - - -/* -=================== -IN_ClearStates -=================== -*/ -void IN_ClearStates (void) -{ - - if (mouseactive) - { - mx_accum = 0; - my_accum = 0; - mouse_oldbuttonstate = 0; - } -} - - -/* -=============== -IN_StartupJoystick -=============== -*/ -void IN_StartupJoystick (void) -{ - int i, numdevs; - JOYCAPS jc; - MMRESULT mmr; - - // assume no joystick - joy_avail = false; - - // abort startup if user requests no joystick - if ( COM_CheckParm ("-nojoy") ) - return; - - // verify joystick driver is present - if ((numdevs = joyGetNumDevs ()) == 0) - { - Con_Printf ("\njoystick not found -- driver not present\n\n"); - return; - } - - // cycle through the joystick ids for the first valid one - for (joy_id=0 ; joy_id 14000.0) - fTemp = 14000.0; - // restore direction information - fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; - } - } - - // convert range from -32768..32767 to -1..1 - fAxisValue /= 32768.0; - - switch (dwAxisMap[i]) - { - case AxisForward: - if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) - { - // user wants forward control to become look control - if (fabs(fAxisValue) > joy_pitchthreshold.value) - { - // if mouse invert is on, invert the joystick pitch value - // only absolute control support here (joy_advanced is false) - if (m_pitch.value < 0.0) - { - cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; - } - else - { - cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; - } - V_StopPitchDrift(); - } - else - { - // no pitch movement - // disable pitch return-to-center unless requested by user - // *** this code can be removed when the lookspring bug is fixed - // *** the bug always has the lookspring feature on - if(lookspring.value == 0.0) - V_StopPitchDrift(); - } - } - else - { - // user wants forward control to be forward control - if (fabs(fAxisValue) > joy_forwardthreshold.value) - { - cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; - } - } - break; - - case AxisSide: - if (fabs(fAxisValue) > joy_sidethreshold.value) - { - cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; - } - break; - - case AxisTurn: - if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) - { - // user wants turn control to become side control - if (fabs(fAxisValue) > joy_sidethreshold.value) - { - cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; - } - } - else - { - // user wants turn control to be turn control - if (fabs(fAxisValue) > joy_yawthreshold.value) - { - if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) - { - cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; - } - else - { - cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; - } - - } - } - break; - - case AxisLook: - if (in_mlook.state & 1) - { - if (fabs(fAxisValue) > joy_pitchthreshold.value) - { - // pitch movement detected and pitch movement desired by user - if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) - { - cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; - } - else - { - cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; - } - V_StopPitchDrift(); - } - else - { - // no pitch movement - // disable pitch return-to-center unless requested by user - // *** this code can be removed when the lookspring bug is fixed - // *** the bug always has the lookspring feature on - if(lookspring.value == 0.0) - V_StopPitchDrift(); - } - } - break; - - default: - break; - } - } - - // bounds check pitch - if (cl.viewangles[PITCH] > 80.0) - cl.viewangles[PITCH] = 80.0; - if (cl.viewangles[PITCH] < -70.0) - cl.viewangles[PITCH] = -70.0; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// in_win.c -- windows 95 mouse and joystick code +// 02/21/97 JCB Added extended DirectInput code to support external controllers. + +#include +#include "quakedef.h" +#include "winquake.h" +#include "dosisms.h" + +#define DINPUT_BUFFERSIZE 16 +#define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) + +HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, + LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); + +// mouse variables +cvar_t m_filter = {"m_filter","0"}; + +int mouse_buttons; +int mouse_oldbuttonstate; +POINT current_pos; +int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; + +static qboolean restore_spi; +static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; + +unsigned int uiWheelMessage; +qboolean mouseactive; +qboolean mouseinitialized; +static qboolean mouseparmsvalid, mouseactivatetoggle; +static qboolean mouseshowtoggle = 1; +static qboolean dinput_acquired; + +static unsigned int mstate_di; + +// joystick defines and variables +// where should defines be moved? +#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick +#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball +#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V +#define JOY_AXIS_X 0 +#define JOY_AXIS_Y 1 +#define JOY_AXIS_Z 2 +#define JOY_AXIS_R 3 +#define JOY_AXIS_U 4 +#define JOY_AXIS_V 5 + +enum _ControlList +{ + AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn +}; + +DWORD dwAxisFlags[JOY_MAX_AXES] = +{ + JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV +}; + +DWORD dwAxisMap[JOY_MAX_AXES]; +DWORD dwControlMap[JOY_MAX_AXES]; +PDWORD pdwRawValue[JOY_MAX_AXES]; + +// none of these cvars are saved over a session +// this means that advanced controller configuration needs to be executed +// each time. this avoids any problems with getting back to a default usage +// or when changing from one controller to another. this way at least something +// works. +cvar_t in_joystick = {"joystick","0", true}; +cvar_t joy_name = {"joyname", "joystick"}; +cvar_t joy_advanced = {"joyadvanced", "0"}; +cvar_t joy_advaxisx = {"joyadvaxisx", "0"}; +cvar_t joy_advaxisy = {"joyadvaxisy", "0"}; +cvar_t joy_advaxisz = {"joyadvaxisz", "0"}; +cvar_t joy_advaxisr = {"joyadvaxisr", "0"}; +cvar_t joy_advaxisu = {"joyadvaxisu", "0"}; +cvar_t joy_advaxisv = {"joyadvaxisv", "0"}; +cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"}; +cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"}; +cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"}; +cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"}; +cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"}; +cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"}; +cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"}; +cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"}; +cvar_t joy_wwhack1 = {"joywwhack1", "0.0"}; +cvar_t joy_wwhack2 = {"joywwhack2", "0.0"}; + +qboolean joy_avail, joy_advancedinit, joy_haspov; +DWORD joy_oldbuttonstate, joy_oldpovstate; + +int joy_id; +DWORD joy_flags; +DWORD joy_numbuttons; + +static LPDIRECTINPUT g_pdi; +static LPDIRECTINPUTDEVICE g_pMouse; + +static JOYINFOEX ji; + +static HINSTANCE hInstDI; + +static qboolean dinput; + +typedef struct MYDATA { + LONG lX; // X axis goes here + LONG lY; // Y axis goes here + LONG lZ; // Z axis goes here + BYTE bButtonA; // One button goes here + BYTE bButtonB; // Another button goes here + BYTE bButtonC; // Another button goes here + BYTE bButtonD; // Another button goes here +} MYDATA; + +static DIOBJECTDATAFORMAT rgodf[] = { + { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, + { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, +}; + +#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) + +static DIDATAFORMAT df = { + sizeof(DIDATAFORMAT), // this structure + sizeof(DIOBJECTDATAFORMAT), // size of object data format + DIDF_RELAXIS, // absolute axis coordinates + sizeof(MYDATA), // device data size + NUM_OBJECTS, // number of objects + rgodf, // and here they are +}; + +// forward-referenced functions +void IN_StartupJoystick (void); +void Joy_AdvancedUpdate_f (void); +void IN_JoyMove (usercmd_t *cmd); + + +/* +=========== +Force_CenterView_f +=========== +*/ +void Force_CenterView_f (void) +{ + cl.viewangles[PITCH] = 0; +} + + +/* +=========== +IN_UpdateClipCursor +=========== +*/ +void IN_UpdateClipCursor (void) +{ + + if (mouseinitialized && mouseactive && !dinput) + { + ClipCursor (&window_rect); + } +} + + +/* +=========== +IN_ShowMouse +=========== +*/ +void IN_ShowMouse (void) +{ + + if (!mouseshowtoggle) + { + ShowCursor (TRUE); + mouseshowtoggle = 1; + } +} + + +/* +=========== +IN_HideMouse +=========== +*/ +void IN_HideMouse (void) +{ + + if (mouseshowtoggle) + { + ShowCursor (FALSE); + mouseshowtoggle = 0; + } +} + + +/* +=========== +IN_ActivateMouse +=========== +*/ +void IN_ActivateMouse (void) +{ + + mouseactivatetoggle = true; + + if (mouseinitialized) + { + if (dinput) + { + if (g_pMouse) + { + if (!dinput_acquired) + { + IDirectInputDevice_Acquire(g_pMouse); + dinput_acquired = true; + } + } + else + { + return; + } + } + else + { + if (mouseparmsvalid) + restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); + + SetCursorPos (window_center_x, window_center_y); + SetCapture (mainwindow); + ClipCursor (&window_rect); + } + + mouseactive = true; + } +} + + +/* +=========== +IN_SetQuakeMouseState +=========== +*/ +void IN_SetQuakeMouseState (void) +{ + if (mouseactivatetoggle) + IN_ActivateMouse (); +} + + +/* +=========== +IN_DeactivateMouse +=========== +*/ +void IN_DeactivateMouse (void) +{ + + mouseactivatetoggle = false; + + if (mouseinitialized) + { + if (dinput) + { + if (g_pMouse) + { + if (dinput_acquired) + { + IDirectInputDevice_Unacquire(g_pMouse); + dinput_acquired = false; + } + } + } + else + { + if (restore_spi) + SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); + + ClipCursor (NULL); + ReleaseCapture (); + } + + mouseactive = false; + } +} + + +/* +=========== +IN_RestoreOriginalMouseState +=========== +*/ +void IN_RestoreOriginalMouseState (void) +{ + if (mouseactivatetoggle) + { + IN_DeactivateMouse (); + mouseactivatetoggle = true; + } + +// try to redraw the cursor so it gets reinitialized, because sometimes it +// has garbage after the mode switch + ShowCursor (TRUE); + ShowCursor (FALSE); +} + + +/* +=========== +IN_InitDInput +=========== +*/ +qboolean IN_InitDInput (void) +{ + HRESULT hr; + DIPROPDWORD dipdw = { + { + sizeof(DIPROPDWORD), // diph.dwSize + sizeof(DIPROPHEADER), // diph.dwHeaderSize + 0, // diph.dwObj + DIPH_DEVICE, // diph.dwHow + }, + DINPUT_BUFFERSIZE, // dwData + }; + + if (!hInstDI) + { + hInstDI = LoadLibrary("dinput.dll"); + + if (hInstDI == NULL) + { + Con_SafePrintf ("Couldn't load dinput.dll\n"); + return false; + } + } + + if (!pDirectInputCreate) + { + pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA"); + + if (!pDirectInputCreate) + { + Con_SafePrintf ("Couldn't get DI proc addr\n"); + return false; + } + } + +// register with DirectInput and get an IDirectInput to play with. + hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); + + if (FAILED(hr)) + { + return false; + } + +// obtain an interface to the system mouse device. + hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't open DI mouse device\n"); + return false; + } + +// set the data format to "mouse format". + hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI mouse format\n"); + return false; + } + +// set the cooperativity level. + hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, + DISCL_EXCLUSIVE | DISCL_FOREGROUND); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI coop level\n"); + return false; + } + + +// set the buffer size to DINPUT_BUFFERSIZE elements. +// the buffer size is a DWORD property associated with the device + hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); + + if (FAILED(hr)) + { + Con_SafePrintf ("Couldn't set DI buffersize\n"); + return false; + } + + return true; +} + + +/* +=========== +IN_StartupMouse +=========== +*/ +void IN_StartupMouse (void) +{ + HDC hdc; + + if ( COM_CheckParm ("-nomouse") ) + return; + + mouseinitialized = true; + + if (COM_CheckParm ("-dinput")) + { + dinput = IN_InitDInput (); + + if (dinput) + { + Con_SafePrintf ("DirectInput initialized\n"); + } + else + { + Con_SafePrintf ("DirectInput not initialized\n"); + } + } + + if (!dinput) + { + mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); + + if (mouseparmsvalid) + { + if ( COM_CheckParm ("-noforcemspd") ) + newmouseparms[2] = originalmouseparms[2]; + + if ( COM_CheckParm ("-noforcemaccel") ) + { + newmouseparms[0] = originalmouseparms[0]; + newmouseparms[1] = originalmouseparms[1]; + } + + if ( COM_CheckParm ("-noforcemparms") ) + { + newmouseparms[0] = originalmouseparms[0]; + newmouseparms[1] = originalmouseparms[1]; + newmouseparms[2] = originalmouseparms[2]; + } + } + } + + mouse_buttons = 3; + +// if a fullscreen video mode was set before the mouse was initialized, +// set the mouse state appropriately + if (mouseactivatetoggle) + IN_ActivateMouse (); +} + + +/* +=========== +IN_Init +=========== +*/ +void IN_Init (void) +{ + // mouse variables + Cvar_RegisterVariable (&m_filter); + + // joystick variables + Cvar_RegisterVariable (&in_joystick); + Cvar_RegisterVariable (&joy_name); + Cvar_RegisterVariable (&joy_advanced); + Cvar_RegisterVariable (&joy_advaxisx); + Cvar_RegisterVariable (&joy_advaxisy); + Cvar_RegisterVariable (&joy_advaxisz); + Cvar_RegisterVariable (&joy_advaxisr); + Cvar_RegisterVariable (&joy_advaxisu); + Cvar_RegisterVariable (&joy_advaxisv); + Cvar_RegisterVariable (&joy_forwardthreshold); + Cvar_RegisterVariable (&joy_sidethreshold); + Cvar_RegisterVariable (&joy_pitchthreshold); + Cvar_RegisterVariable (&joy_yawthreshold); + Cvar_RegisterVariable (&joy_forwardsensitivity); + Cvar_RegisterVariable (&joy_sidesensitivity); + Cvar_RegisterVariable (&joy_pitchsensitivity); + Cvar_RegisterVariable (&joy_yawsensitivity); + Cvar_RegisterVariable (&joy_wwhack1); + Cvar_RegisterVariable (&joy_wwhack2); + + Cmd_AddCommand ("force_centerview", Force_CenterView_f); + Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); + + uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); + + IN_StartupMouse (); + IN_StartupJoystick (); +} + +/* +=========== +IN_Shutdown +=========== +*/ +void IN_Shutdown (void) +{ + + IN_DeactivateMouse (); + IN_ShowMouse (); + + if (g_pMouse) + { + IDirectInputDevice_Release(g_pMouse); + g_pMouse = NULL; + } + + if (g_pdi) + { + IDirectInput_Release(g_pdi); + g_pdi = NULL; + } +} + + +/* +=========== +IN_MouseEvent +=========== +*/ +void IN_MouseEvent (int mstate) +{ + int i; + + if (mouseactive && !dinput) + { + // perform button actions + for (i=0 ; isidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + if (in_mlook.state & 1) + V_StopPitchDrift (); + + if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + if (cl.viewangles[PITCH] > 80) + cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] < -70) + cl.viewangles[PITCH] = -70; + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } + +// if the mouse has moved, force it to the center, so there's room to move + if (mx || my) + { + SetCursorPos (window_center_x, window_center_y); + } +} + + +/* +=========== +IN_Move +=========== +*/ +void IN_Move (usercmd_t *cmd) +{ + + if (ActiveApp && !Minimized) + { + IN_MouseMove (cmd); + IN_JoyMove (cmd); + } +} + + +/* +=========== +IN_Accumulate +=========== +*/ +void IN_Accumulate (void) +{ + int mx, my; + HDC hdc; + + if (mouseactive) + { + if (!dinput) + { + GetCursorPos (¤t_pos); + + mx_accum += current_pos.x - window_center_x; + my_accum += current_pos.y - window_center_y; + + // force the mouse to the center, so there's room to move + SetCursorPos (window_center_x, window_center_y); + } + } +} + + +/* +=================== +IN_ClearStates +=================== +*/ +void IN_ClearStates (void) +{ + + if (mouseactive) + { + mx_accum = 0; + my_accum = 0; + mouse_oldbuttonstate = 0; + } +} + + +/* +=============== +IN_StartupJoystick +=============== +*/ +void IN_StartupJoystick (void) +{ + int i, numdevs; + JOYCAPS jc; + MMRESULT mmr; + + // assume no joystick + joy_avail = false; + + // abort startup if user requests no joystick + if ( COM_CheckParm ("-nojoy") ) + return; + + // verify joystick driver is present + if ((numdevs = joyGetNumDevs ()) == 0) + { + Con_Printf ("\njoystick not found -- driver not present\n\n"); + return; + } + + // cycle through the joystick ids for the first valid one + for (joy_id=0 ; joy_id 14000.0) + fTemp = 14000.0; + // restore direction information + fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; + } + } + + // convert range from -32768..32767 to -1..1 + fAxisValue /= 32768.0; + + switch (dwAxisMap[i]) + { + case AxisForward: + if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) + { + // user wants forward control to become look control + if (fabs(fAxisValue) > joy_pitchthreshold.value) + { + // if mouse invert is on, invert the joystick pitch value + // only absolute control support here (joy_advanced is false) + if (m_pitch.value < 0.0) + { + cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.value == 0.0) + V_StopPitchDrift(); + } + } + else + { + // user wants forward control to be forward control + if (fabs(fAxisValue) > joy_forwardthreshold.value) + { + cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; + } + } + break; + + case AxisSide: + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } + break; + + case AxisTurn: + if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) + { + // user wants turn control to become side control + if (fabs(fAxisValue) > joy_sidethreshold.value) + { + cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + } + } + else + { + // user wants turn control to be turn control + if (fabs(fAxisValue) > joy_yawthreshold.value) + { + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; + } + else + { + cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; + } + + } + } + break; + + case AxisLook: + if (in_mlook.state & 1) + { + if (fabs(fAxisValue) > joy_pitchthreshold.value) + { + // pitch movement detected and pitch movement desired by user + if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; + } + else + { + cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; + } + V_StopPitchDrift(); + } + else + { + // no pitch movement + // disable pitch return-to-center unless requested by user + // *** this code can be removed when the lookspring bug is fixed + // *** the bug always has the lookspring feature on + if(lookspring.value == 0.0) + V_StopPitchDrift(); + } + } + break; + + default: + break; + } + } + + // bounds check pitch + if (cl.viewangles[PITCH] > 80.0) + cl.viewangles[PITCH] = 80.0; + if (cl.viewangles[PITCH] < -70.0) + cl.viewangles[PITCH] = -70.0; +} diff --git a/WinQuake/input.h b/WinQuake/input.h index c3daa17..ae888f9 100644 --- a/WinQuake/input.h +++ b/WinQuake/input.h @@ -1,34 +1,34 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// input.h -- external (non-keyboard) input devices - -void IN_Init (void); - -void IN_Shutdown (void); - -void IN_Commands (void); -// oportunity for devices to stick commands on the script buffer - -void IN_Move (usercmd_t *cmd); -// add additional movement on top of the keyboard move cmd - -void IN_ClearStates (void); -// restores all button and position states to defaults - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// input.h -- external (non-keyboard) input devices + +void IN_Init (void); + +void IN_Shutdown (void); + +void IN_Commands (void); +// oportunity for devices to stick commands on the script buffer + +void IN_Move (usercmd_t *cmd); +// add additional movement on top of the keyboard move cmd + +void IN_ClearStates (void); +// restores all button and position states to defaults + diff --git a/WinQuake/keys.c b/WinQuake/keys.c index 6e48ad4..5534056 100644 --- a/WinQuake/keys.c +++ b/WinQuake/keys.c @@ -1,759 +1,759 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -/* - -key up events are sent even if in console mode - -*/ - - -#define MAXCMDLINE 256 -char key_lines[32][MAXCMDLINE]; -int key_linepos; -int shift_down=false; -int key_lastpress; - -int edit_line=0; -int history_line=0; - -keydest_t key_dest; - -int key_count; // incremented every key event - -char *keybindings[256]; -qboolean consolekeys[256]; // if true, can't be rebound while in console -qboolean menubound[256]; // if true, can't be rebound while in menu -int keyshift[256]; // key to map to if shift held down in console -int key_repeats[256]; // if > 1, it is autorepeating -qboolean keydown[256]; - -typedef struct -{ - char *name; - int keynum; -} keyname_t; - -keyname_t keynames[] = -{ - {"TAB", K_TAB}, - {"ENTER", K_ENTER}, - {"ESCAPE", K_ESCAPE}, - {"SPACE", K_SPACE}, - {"BACKSPACE", K_BACKSPACE}, - {"UPARROW", K_UPARROW}, - {"DOWNARROW", K_DOWNARROW}, - {"LEFTARROW", K_LEFTARROW}, - {"RIGHTARROW", K_RIGHTARROW}, - - {"ALT", K_ALT}, - {"CTRL", K_CTRL}, - {"SHIFT", K_SHIFT}, - - {"F1", K_F1}, - {"F2", K_F2}, - {"F3", K_F3}, - {"F4", K_F4}, - {"F5", K_F5}, - {"F6", K_F6}, - {"F7", K_F7}, - {"F8", K_F8}, - {"F9", K_F9}, - {"F10", K_F10}, - {"F11", K_F11}, - {"F12", K_F12}, - - {"INS", K_INS}, - {"DEL", K_DEL}, - {"PGDN", K_PGDN}, - {"PGUP", K_PGUP}, - {"HOME", K_HOME}, - {"END", K_END}, - - {"MOUSE1", K_MOUSE1}, - {"MOUSE2", K_MOUSE2}, - {"MOUSE3", K_MOUSE3}, - - {"JOY1", K_JOY1}, - {"JOY2", K_JOY2}, - {"JOY3", K_JOY3}, - {"JOY4", K_JOY4}, - - {"AUX1", K_AUX1}, - {"AUX2", K_AUX2}, - {"AUX3", K_AUX3}, - {"AUX4", K_AUX4}, - {"AUX5", K_AUX5}, - {"AUX6", K_AUX6}, - {"AUX7", K_AUX7}, - {"AUX8", K_AUX8}, - {"AUX9", K_AUX9}, - {"AUX10", K_AUX10}, - {"AUX11", K_AUX11}, - {"AUX12", K_AUX12}, - {"AUX13", K_AUX13}, - {"AUX14", K_AUX14}, - {"AUX15", K_AUX15}, - {"AUX16", K_AUX16}, - {"AUX17", K_AUX17}, - {"AUX18", K_AUX18}, - {"AUX19", K_AUX19}, - {"AUX20", K_AUX20}, - {"AUX21", K_AUX21}, - {"AUX22", K_AUX22}, - {"AUX23", K_AUX23}, - {"AUX24", K_AUX24}, - {"AUX25", K_AUX25}, - {"AUX26", K_AUX26}, - {"AUX27", K_AUX27}, - {"AUX28", K_AUX28}, - {"AUX29", K_AUX29}, - {"AUX30", K_AUX30}, - {"AUX31", K_AUX31}, - {"AUX32", K_AUX32}, - - {"PAUSE", K_PAUSE}, - - {"MWHEELUP", K_MWHEELUP}, - {"MWHEELDOWN", K_MWHEELDOWN}, - - {"SEMICOLON", ';'}, // because a raw semicolon seperates commands - - {NULL,0} -}; - -/* -============================================================================== - - LINE TYPING INTO THE CONSOLE - -============================================================================== -*/ - - -/* -==================== -Key_Console - -Interactive line editing and console scrollback -==================== -*/ -void Key_Console (int key) -{ - char *cmd; - - if (key == K_ENTER) - { - Cbuf_AddText (key_lines[edit_line]+1); // skip the > - Cbuf_AddText ("\n"); - Con_Printf ("%s\n",key_lines[edit_line]); - edit_line = (edit_line + 1) & 31; - history_line = edit_line; - key_lines[edit_line][0] = ']'; - key_linepos = 1; - if (cls.state == ca_disconnected) - SCR_UpdateScreen (); // force an update, because the command - // may take some time - return; - } - - if (key == K_TAB) - { // command completion - cmd = Cmd_CompleteCommand (key_lines[edit_line]+1); - if (!cmd) - cmd = Cvar_CompleteVariable (key_lines[edit_line]+1); - if (cmd) - { - Q_strcpy (key_lines[edit_line]+1, cmd); - key_linepos = Q_strlen(cmd)+1; - key_lines[edit_line][key_linepos] = ' '; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - return; - } - } - - if (key == K_BACKSPACE || key == K_LEFTARROW) - { - if (key_linepos > 1) - key_linepos--; - return; - } - - if (key == K_UPARROW) - { - do - { - history_line = (history_line - 1) & 31; - } while (history_line != edit_line - && !key_lines[history_line][1]); - if (history_line == edit_line) - history_line = (edit_line+1)&31; - Q_strcpy(key_lines[edit_line], key_lines[history_line]); - key_linepos = Q_strlen(key_lines[edit_line]); - return; - } - - if (key == K_DOWNARROW) - { - if (history_line == edit_line) return; - do - { - history_line = (history_line + 1) & 31; - } - while (history_line != edit_line - && !key_lines[history_line][1]); - if (history_line == edit_line) - { - key_lines[edit_line][0] = ']'; - key_linepos = 1; - } - else - { - Q_strcpy(key_lines[edit_line], key_lines[history_line]); - key_linepos = Q_strlen(key_lines[edit_line]); - } - return; - } - - if (key == K_PGUP || key==K_MWHEELUP) - { - con_backscroll += 2; - if (con_backscroll > con_totallines - (vid.height>>3) - 1) - con_backscroll = con_totallines - (vid.height>>3) - 1; - return; - } - - if (key == K_PGDN || key==K_MWHEELDOWN) - { - con_backscroll -= 2; - if (con_backscroll < 0) - con_backscroll = 0; - return; - } - - if (key == K_HOME) - { - con_backscroll = con_totallines - (vid.height>>3) - 1; - return; - } - - if (key == K_END) - { - con_backscroll = 0; - return; - } - - if (key < 32 || key > 127) - return; // non printable - - if (key_linepos < MAXCMDLINE-1) - { - key_lines[edit_line][key_linepos] = key; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - } - -} - -//============================================================================ - -char chat_buffer[32]; -qboolean team_message = false; - -void Key_Message (int key) -{ - static int chat_bufferlen = 0; - - if (key == K_ENTER) - { - if (team_message) - Cbuf_AddText ("say_team \""); - else - Cbuf_AddText ("say \""); - Cbuf_AddText(chat_buffer); - Cbuf_AddText("\"\n"); - - key_dest = key_game; - chat_bufferlen = 0; - chat_buffer[0] = 0; - return; - } - - if (key == K_ESCAPE) - { - key_dest = key_game; - chat_bufferlen = 0; - chat_buffer[0] = 0; - return; - } - - if (key < 32 || key > 127) - return; // non printable - - if (key == K_BACKSPACE) - { - if (chat_bufferlen) - { - chat_bufferlen--; - chat_buffer[chat_bufferlen] = 0; - } - return; - } - - if (chat_bufferlen == 31) - return; // all full - - chat_buffer[chat_bufferlen++] = key; - chat_buffer[chat_bufferlen] = 0; -} - -//============================================================================ - - -/* -=================== -Key_StringToKeynum - -Returns a key number to be used to index keybindings[] by looking at -the given string. Single ascii characters return themselves, while -the K_* names are matched up. -=================== -*/ -int Key_StringToKeynum (char *str) -{ - keyname_t *kn; - - if (!str || !str[0]) - return -1; - if (!str[1]) - return str[0]; - - for (kn=keynames ; kn->name ; kn++) - { - if (!Q_strcasecmp(str,kn->name)) - return kn->keynum; - } - return -1; -} - -/* -=================== -Key_KeynumToString - -Returns a string (either a single ascii char, or a K_* name) for the -given keynum. -FIXME: handle quote special (general escape sequence?) -=================== -*/ -char *Key_KeynumToString (int keynum) -{ - keyname_t *kn; - static char tinystr[2]; - - if (keynum == -1) - return ""; - if (keynum > 32 && keynum < 127) - { // printable ascii - tinystr[0] = keynum; - tinystr[1] = 0; - return tinystr; - } - - for (kn=keynames ; kn->name ; kn++) - if (keynum == kn->keynum) - return kn->name; - - return ""; -} - - -/* -=================== -Key_SetBinding -=================== -*/ -void Key_SetBinding (int keynum, char *binding) -{ - char *new; - int l; - - if (keynum == -1) - return; - -// free old bindings - if (keybindings[keynum]) - { - Z_Free (keybindings[keynum]); - keybindings[keynum] = NULL; - } - -// allocate memory for new binding - l = Q_strlen (binding); - new = Z_Malloc (l+1); - Q_strcpy (new, binding); - new[l] = 0; - keybindings[keynum] = new; -} - -/* -=================== -Key_Unbind_f -=================== -*/ -void Key_Unbind_f (void) -{ - int b; - - if (Cmd_Argc() != 2) - { - Con_Printf ("unbind : remove commands from a key\n"); - return; - } - - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } - - Key_SetBinding (b, ""); -} - -void Key_Unbindall_f (void) -{ - int i; - - for (i=0 ; i<256 ; i++) - if (keybindings[i]) - Key_SetBinding (i, ""); -} - - -/* -=================== -Key_Bind_f -=================== -*/ -void Key_Bind_f (void) -{ - int i, c, b; - char cmd[1024]; - - c = Cmd_Argc(); - - if (c != 2 && c != 3) - { - Con_Printf ("bind [command] : attach a command to a key\n"); - return; - } - b = Key_StringToKeynum (Cmd_Argv(1)); - if (b==-1) - { - Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); - return; - } - - if (c == 2) - { - if (keybindings[b]) - Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); - else - Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); - return; - } - -// copy the rest of the command line - cmd[0] = 0; // start out with a null string - for (i=2 ; i< c ; i++) - { - if (i > 2) - strcat (cmd, " "); - strcat (cmd, Cmd_Argv(i)); - } - - Key_SetBinding (b, cmd); -} - -/* -============ -Key_WriteBindings - -Writes lines containing "bind key value" -============ -*/ -void Key_WriteBindings (FILE *f) -{ - int i; - - for (i=0 ; i<256 ; i++) - if (keybindings[i]) - if (*keybindings[i]) - fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]); -} - - -/* -=================== -Key_Init -=================== -*/ -void Key_Init (void) -{ - int i; - - for (i=0 ; i<32 ; i++) - { - key_lines[i][0] = ']'; - key_lines[i][1] = 0; - } - key_linepos = 1; - -// -// init ascii characters in console mode -// - for (i=32 ; i<128 ; i++) - consolekeys[i] = true; - consolekeys[K_ENTER] = true; - consolekeys[K_TAB] = true; - consolekeys[K_LEFTARROW] = true; - consolekeys[K_RIGHTARROW] = true; - consolekeys[K_UPARROW] = true; - consolekeys[K_DOWNARROW] = true; - consolekeys[K_BACKSPACE] = true; - consolekeys[K_PGUP] = true; - consolekeys[K_PGDN] = true; - consolekeys[K_SHIFT] = true; - consolekeys[K_MWHEELUP] = true; - consolekeys[K_MWHEELDOWN] = true; - consolekeys['`'] = false; - consolekeys['~'] = false; - - for (i=0 ; i<256 ; i++) - keyshift[i] = i; - for (i='a' ; i<='z' ; i++) - keyshift[i] = i - 'a' + 'A'; - keyshift['1'] = '!'; - keyshift['2'] = '@'; - keyshift['3'] = '#'; - keyshift['4'] = '$'; - keyshift['5'] = '%'; - keyshift['6'] = '^'; - keyshift['7'] = '&'; - keyshift['8'] = '*'; - keyshift['9'] = '('; - keyshift['0'] = ')'; - keyshift['-'] = '_'; - keyshift['='] = '+'; - keyshift[','] = '<'; - keyshift['.'] = '>'; - keyshift['/'] = '?'; - keyshift[';'] = ':'; - keyshift['\''] = '"'; - keyshift['['] = '{'; - keyshift[']'] = '}'; - keyshift['`'] = '~'; - keyshift['\\'] = '|'; - - menubound[K_ESCAPE] = true; - for (i=0 ; i<12 ; i++) - menubound[K_F1+i] = true; - -// -// register our functions -// - Cmd_AddCommand ("bind",Key_Bind_f); - Cmd_AddCommand ("unbind",Key_Unbind_f); - Cmd_AddCommand ("unbindall",Key_Unbindall_f); - - -} - -/* -=================== -Key_Event - -Called by the system between frames for both key up and key down events -Should NOT be called during an interrupt! -=================== -*/ -void Key_Event (int key, qboolean down) -{ - char *kb; - char cmd[1024]; - - keydown[key] = down; - - if (!down) - key_repeats[key] = 0; - - key_lastpress = key; - key_count++; - if (key_count <= 0) - { - return; // just catching keys for Con_NotifyBox - } - -// update auto-repeat status - if (down) - { - key_repeats[key]++; - if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1) - { - return; // ignore most autorepeats - } - - if (key >= 200 && !keybindings[key]) - Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); - } - - if (key == K_SHIFT) - shift_down = down; - -// -// handle escape specialy, so the user can never unbind it -// - if (key == K_ESCAPE) - { - if (!down) - return; - switch (key_dest) - { - case key_message: - Key_Message (key); - break; - case key_menu: - M_Keydown (key); - break; - case key_game: - case key_console: - M_ToggleMenu_f (); - break; - default: - Sys_Error ("Bad key_dest"); - } - return; - } - -// -// key up events only generate commands if the game key binding is -// a button command (leading + sign). These will occur even in console mode, -// to keep the character from continuing an action started before a console -// switch. Button commands include the kenum as a parameter, so multiple -// downs can be matched with ups -// - if (!down) - { - kb = keybindings[key]; - if (kb && kb[0] == '+') - { - sprintf (cmd, "-%s %i\n", kb+1, key); - Cbuf_AddText (cmd); - } - if (keyshift[key] != key) - { - kb = keybindings[keyshift[key]]; - if (kb && kb[0] == '+') - { - sprintf (cmd, "-%s %i\n", kb+1, key); - Cbuf_AddText (cmd); - } - } - return; - } - -// -// during demo playback, most keys bring up the main menu -// - if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) - { - M_ToggleMenu_f (); - return; - } - -// -// if not a consolekey, send to the interpreter no matter what mode is -// - if ( (key_dest == key_menu && menubound[key]) - || (key_dest == key_console && !consolekeys[key]) - || (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) ) - { - kb = keybindings[key]; - if (kb) - { - if (kb[0] == '+') - { // button commands add keynum as a parm - sprintf (cmd, "%s %i\n", kb, key); - Cbuf_AddText (cmd); - } - else - { - Cbuf_AddText (kb); - Cbuf_AddText ("\n"); - } - } - return; - } - - if (!down) - return; // other systems only care about key down events - - if (shift_down) - { - key = keyshift[key]; - } - - switch (key_dest) - { - case key_message: - Key_Message (key); - break; - case key_menu: - M_Keydown (key); - break; - - case key_game: - case key_console: - Key_Console (key); - break; - default: - Sys_Error ("Bad key_dest"); - } -} - - -/* -=================== -Key_ClearStates -=================== -*/ -void Key_ClearStates (void) -{ - int i; - - for (i=0 ; i<256 ; i++) - { - keydown[i] = false; - key_repeats[i] = 0; - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +/* + +key up events are sent even if in console mode + +*/ + + +#define MAXCMDLINE 256 +char key_lines[32][MAXCMDLINE]; +int key_linepos; +int shift_down=false; +int key_lastpress; + +int edit_line=0; +int history_line=0; + +keydest_t key_dest; + +int key_count; // incremented every key event + +char *keybindings[256]; +qboolean consolekeys[256]; // if true, can't be rebound while in console +qboolean menubound[256]; // if true, can't be rebound while in menu +int keyshift[256]; // key to map to if shift held down in console +int key_repeats[256]; // if > 1, it is autorepeating +qboolean keydown[256]; + +typedef struct +{ + char *name; + int keynum; +} keyname_t; + +keyname_t keynames[] = +{ + {"TAB", K_TAB}, + {"ENTER", K_ENTER}, + {"ESCAPE", K_ESCAPE}, + {"SPACE", K_SPACE}, + {"BACKSPACE", K_BACKSPACE}, + {"UPARROW", K_UPARROW}, + {"DOWNARROW", K_DOWNARROW}, + {"LEFTARROW", K_LEFTARROW}, + {"RIGHTARROW", K_RIGHTARROW}, + + {"ALT", K_ALT}, + {"CTRL", K_CTRL}, + {"SHIFT", K_SHIFT}, + + {"F1", K_F1}, + {"F2", K_F2}, + {"F3", K_F3}, + {"F4", K_F4}, + {"F5", K_F5}, + {"F6", K_F6}, + {"F7", K_F7}, + {"F8", K_F8}, + {"F9", K_F9}, + {"F10", K_F10}, + {"F11", K_F11}, + {"F12", K_F12}, + + {"INS", K_INS}, + {"DEL", K_DEL}, + {"PGDN", K_PGDN}, + {"PGUP", K_PGUP}, + {"HOME", K_HOME}, + {"END", K_END}, + + {"MOUSE1", K_MOUSE1}, + {"MOUSE2", K_MOUSE2}, + {"MOUSE3", K_MOUSE3}, + + {"JOY1", K_JOY1}, + {"JOY2", K_JOY2}, + {"JOY3", K_JOY3}, + {"JOY4", K_JOY4}, + + {"AUX1", K_AUX1}, + {"AUX2", K_AUX2}, + {"AUX3", K_AUX3}, + {"AUX4", K_AUX4}, + {"AUX5", K_AUX5}, + {"AUX6", K_AUX6}, + {"AUX7", K_AUX7}, + {"AUX8", K_AUX8}, + {"AUX9", K_AUX9}, + {"AUX10", K_AUX10}, + {"AUX11", K_AUX11}, + {"AUX12", K_AUX12}, + {"AUX13", K_AUX13}, + {"AUX14", K_AUX14}, + {"AUX15", K_AUX15}, + {"AUX16", K_AUX16}, + {"AUX17", K_AUX17}, + {"AUX18", K_AUX18}, + {"AUX19", K_AUX19}, + {"AUX20", K_AUX20}, + {"AUX21", K_AUX21}, + {"AUX22", K_AUX22}, + {"AUX23", K_AUX23}, + {"AUX24", K_AUX24}, + {"AUX25", K_AUX25}, + {"AUX26", K_AUX26}, + {"AUX27", K_AUX27}, + {"AUX28", K_AUX28}, + {"AUX29", K_AUX29}, + {"AUX30", K_AUX30}, + {"AUX31", K_AUX31}, + {"AUX32", K_AUX32}, + + {"PAUSE", K_PAUSE}, + + {"MWHEELUP", K_MWHEELUP}, + {"MWHEELDOWN", K_MWHEELDOWN}, + + {"SEMICOLON", ';'}, // because a raw semicolon seperates commands + + {NULL,0} +}; + +/* +============================================================================== + + LINE TYPING INTO THE CONSOLE + +============================================================================== +*/ + + +/* +==================== +Key_Console + +Interactive line editing and console scrollback +==================== +*/ +void Key_Console (int key) +{ + char *cmd; + + if (key == K_ENTER) + { + Cbuf_AddText (key_lines[edit_line]+1); // skip the > + Cbuf_AddText ("\n"); + Con_Printf ("%s\n",key_lines[edit_line]); + edit_line = (edit_line + 1) & 31; + history_line = edit_line; + key_lines[edit_line][0] = ']'; + key_linepos = 1; + if (cls.state == ca_disconnected) + SCR_UpdateScreen (); // force an update, because the command + // may take some time + return; + } + + if (key == K_TAB) + { // command completion + cmd = Cmd_CompleteCommand (key_lines[edit_line]+1); + if (!cmd) + cmd = Cvar_CompleteVariable (key_lines[edit_line]+1); + if (cmd) + { + Q_strcpy (key_lines[edit_line]+1, cmd); + key_linepos = Q_strlen(cmd)+1; + key_lines[edit_line][key_linepos] = ' '; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + return; + } + } + + if (key == K_BACKSPACE || key == K_LEFTARROW) + { + if (key_linepos > 1) + key_linepos--; + return; + } + + if (key == K_UPARROW) + { + do + { + history_line = (history_line - 1) & 31; + } while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + history_line = (edit_line+1)&31; + Q_strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + return; + } + + if (key == K_DOWNARROW) + { + if (history_line == edit_line) return; + do + { + history_line = (history_line + 1) & 31; + } + while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + { + key_lines[edit_line][0] = ']'; + key_linepos = 1; + } + else + { + Q_strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + } + return; + } + + if (key == K_PGUP || key==K_MWHEELUP) + { + con_backscroll += 2; + if (con_backscroll > con_totallines - (vid.height>>3) - 1) + con_backscroll = con_totallines - (vid.height>>3) - 1; + return; + } + + if (key == K_PGDN || key==K_MWHEELDOWN) + { + con_backscroll -= 2; + if (con_backscroll < 0) + con_backscroll = 0; + return; + } + + if (key == K_HOME) + { + con_backscroll = con_totallines - (vid.height>>3) - 1; + return; + } + + if (key == K_END) + { + con_backscroll = 0; + return; + } + + if (key < 32 || key > 127) + return; // non printable + + if (key_linepos < MAXCMDLINE-1) + { + key_lines[edit_line][key_linepos] = key; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + } + +} + +//============================================================================ + +char chat_buffer[32]; +qboolean team_message = false; + +void Key_Message (int key) +{ + static int chat_bufferlen = 0; + + if (key == K_ENTER) + { + if (team_message) + Cbuf_AddText ("say_team \""); + else + Cbuf_AddText ("say \""); + Cbuf_AddText(chat_buffer); + Cbuf_AddText("\"\n"); + + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key == K_ESCAPE) + { + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key < 32 || key > 127) + return; // non printable + + if (key == K_BACKSPACE) + { + if (chat_bufferlen) + { + chat_bufferlen--; + chat_buffer[chat_bufferlen] = 0; + } + return; + } + + if (chat_bufferlen == 31) + return; // all full + + chat_buffer[chat_bufferlen++] = key; + chat_buffer[chat_bufferlen] = 0; +} + +//============================================================================ + + +/* +=================== +Key_StringToKeynum + +Returns a key number to be used to index keybindings[] by looking at +the given string. Single ascii characters return themselves, while +the K_* names are matched up. +=================== +*/ +int Key_StringToKeynum (char *str) +{ + keyname_t *kn; + + if (!str || !str[0]) + return -1; + if (!str[1]) + return str[0]; + + for (kn=keynames ; kn->name ; kn++) + { + if (!Q_strcasecmp(str,kn->name)) + return kn->keynum; + } + return -1; +} + +/* +=================== +Key_KeynumToString + +Returns a string (either a single ascii char, or a K_* name) for the +given keynum. +FIXME: handle quote special (general escape sequence?) +=================== +*/ +char *Key_KeynumToString (int keynum) +{ + keyname_t *kn; + static char tinystr[2]; + + if (keynum == -1) + return ""; + if (keynum > 32 && keynum < 127) + { // printable ascii + tinystr[0] = keynum; + tinystr[1] = 0; + return tinystr; + } + + for (kn=keynames ; kn->name ; kn++) + if (keynum == kn->keynum) + return kn->name; + + return ""; +} + + +/* +=================== +Key_SetBinding +=================== +*/ +void Key_SetBinding (int keynum, char *binding) +{ + char *new; + int l; + + if (keynum == -1) + return; + +// free old bindings + if (keybindings[keynum]) + { + Z_Free (keybindings[keynum]); + keybindings[keynum] = NULL; + } + +// allocate memory for new binding + l = Q_strlen (binding); + new = Z_Malloc (l+1); + Q_strcpy (new, binding); + new[l] = 0; + keybindings[keynum] = new; +} + +/* +=================== +Key_Unbind_f +=================== +*/ +void Key_Unbind_f (void) +{ + int b; + + if (Cmd_Argc() != 2) + { + Con_Printf ("unbind : remove commands from a key\n"); + return; + } + + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + Key_SetBinding (b, ""); +} + +void Key_Unbindall_f (void) +{ + int i; + + for (i=0 ; i<256 ; i++) + if (keybindings[i]) + Key_SetBinding (i, ""); +} + + +/* +=================== +Key_Bind_f +=================== +*/ +void Key_Bind_f (void) +{ + int i, c, b; + char cmd[1024]; + + c = Cmd_Argc(); + + if (c != 2 && c != 3) + { + Con_Printf ("bind [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + if (c == 2) + { + if (keybindings[b]) + Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); + else + Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); + return; + } + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i=2 ; i< c ; i++) + { + if (i > 2) + strcat (cmd, " "); + strcat (cmd, Cmd_Argv(i)); + } + + Key_SetBinding (b, cmd); +} + +/* +============ +Key_WriteBindings + +Writes lines containing "bind key value" +============ +*/ +void Key_WriteBindings (FILE *f) +{ + int i; + + for (i=0 ; i<256 ; i++) + if (keybindings[i]) + if (*keybindings[i]) + fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]); +} + + +/* +=================== +Key_Init +=================== +*/ +void Key_Init (void) +{ + int i; + + for (i=0 ; i<32 ; i++) + { + key_lines[i][0] = ']'; + key_lines[i][1] = 0; + } + key_linepos = 1; + +// +// init ascii characters in console mode +// + for (i=32 ; i<128 ; i++) + consolekeys[i] = true; + consolekeys[K_ENTER] = true; + consolekeys[K_TAB] = true; + consolekeys[K_LEFTARROW] = true; + consolekeys[K_RIGHTARROW] = true; + consolekeys[K_UPARROW] = true; + consolekeys[K_DOWNARROW] = true; + consolekeys[K_BACKSPACE] = true; + consolekeys[K_PGUP] = true; + consolekeys[K_PGDN] = true; + consolekeys[K_SHIFT] = true; + consolekeys[K_MWHEELUP] = true; + consolekeys[K_MWHEELDOWN] = true; + consolekeys['`'] = false; + consolekeys['~'] = false; + + for (i=0 ; i<256 ; i++) + keyshift[i] = i; + for (i='a' ; i<='z' ; i++) + keyshift[i] = i - 'a' + 'A'; + keyshift['1'] = '!'; + keyshift['2'] = '@'; + keyshift['3'] = '#'; + keyshift['4'] = '$'; + keyshift['5'] = '%'; + keyshift['6'] = '^'; + keyshift['7'] = '&'; + keyshift['8'] = '*'; + keyshift['9'] = '('; + keyshift['0'] = ')'; + keyshift['-'] = '_'; + keyshift['='] = '+'; + keyshift[','] = '<'; + keyshift['.'] = '>'; + keyshift['/'] = '?'; + keyshift[';'] = ':'; + keyshift['\''] = '"'; + keyshift['['] = '{'; + keyshift[']'] = '}'; + keyshift['`'] = '~'; + keyshift['\\'] = '|'; + + menubound[K_ESCAPE] = true; + for (i=0 ; i<12 ; i++) + menubound[K_F1+i] = true; + +// +// register our functions +// + Cmd_AddCommand ("bind",Key_Bind_f); + Cmd_AddCommand ("unbind",Key_Unbind_f); + Cmd_AddCommand ("unbindall",Key_Unbindall_f); + + +} + +/* +=================== +Key_Event + +Called by the system between frames for both key up and key down events +Should NOT be called during an interrupt! +=================== +*/ +void Key_Event (int key, qboolean down) +{ + char *kb; + char cmd[1024]; + + keydown[key] = down; + + if (!down) + key_repeats[key] = 0; + + key_lastpress = key; + key_count++; + if (key_count <= 0) + { + return; // just catching keys for Con_NotifyBox + } + +// update auto-repeat status + if (down) + { + key_repeats[key]++; + if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1) + { + return; // ignore most autorepeats + } + + if (key >= 200 && !keybindings[key]) + Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); + } + + if (key == K_SHIFT) + shift_down = down; + +// +// handle escape specialy, so the user can never unbind it +// + if (key == K_ESCAPE) + { + if (!down) + return; + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + M_Keydown (key); + break; + case key_game: + case key_console: + M_ToggleMenu_f (); + break; + default: + Sys_Error ("Bad key_dest"); + } + return; + } + +// +// key up events only generate commands if the game key binding is +// a button command (leading + sign). These will occur even in console mode, +// to keep the character from continuing an action started before a console +// switch. Button commands include the kenum as a parameter, so multiple +// downs can be matched with ups +// + if (!down) + { + kb = keybindings[key]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + if (keyshift[key] != key) + { + kb = keybindings[keyshift[key]]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + } + return; + } + +// +// during demo playback, most keys bring up the main menu +// + if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) + { + M_ToggleMenu_f (); + return; + } + +// +// if not a consolekey, send to the interpreter no matter what mode is +// + if ( (key_dest == key_menu && menubound[key]) + || (key_dest == key_console && !consolekeys[key]) + || (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) ) + { + kb = keybindings[key]; + if (kb) + { + if (kb[0] == '+') + { // button commands add keynum as a parm + sprintf (cmd, "%s %i\n", kb, key); + Cbuf_AddText (cmd); + } + else + { + Cbuf_AddText (kb); + Cbuf_AddText ("\n"); + } + } + return; + } + + if (!down) + return; // other systems only care about key down events + + if (shift_down) + { + key = keyshift[key]; + } + + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + M_Keydown (key); + break; + + case key_game: + case key_console: + Key_Console (key); + break; + default: + Sys_Error ("Bad key_dest"); + } +} + + +/* +=================== +Key_ClearStates +=================== +*/ +void Key_ClearStates (void) +{ + int i; + + for (i=0 ; i<256 ; i++) + { + keydown[i] = false; + key_repeats[i] = 0; + } +} + diff --git a/WinQuake/keys.h b/WinQuake/keys.h index 3fbefd0..986c9d0 100644 --- a/WinQuake/keys.h +++ b/WinQuake/keys.h @@ -1,133 +1,133 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// -// these are the key numbers that should be passed to Key_Event -// -#define K_TAB 9 -#define K_ENTER 13 -#define K_ESCAPE 27 -#define K_SPACE 32 - -// normal keys should be passed as lowercased ascii - -#define K_BACKSPACE 127 -#define K_UPARROW 128 -#define K_DOWNARROW 129 -#define K_LEFTARROW 130 -#define K_RIGHTARROW 131 - -#define K_ALT 132 -#define K_CTRL 133 -#define K_SHIFT 134 -#define K_F1 135 -#define K_F2 136 -#define K_F3 137 -#define K_F4 138 -#define K_F5 139 -#define K_F6 140 -#define K_F7 141 -#define K_F8 142 -#define K_F9 143 -#define K_F10 144 -#define K_F11 145 -#define K_F12 146 -#define K_INS 147 -#define K_DEL 148 -#define K_PGDN 149 -#define K_PGUP 150 -#define K_HOME 151 -#define K_END 152 - -#define K_PAUSE 255 - -// -// mouse buttons generate virtual keys -// -#define K_MOUSE1 200 -#define K_MOUSE2 201 -#define K_MOUSE3 202 - -// -// joystick buttons -// -#define K_JOY1 203 -#define K_JOY2 204 -#define K_JOY3 205 -#define K_JOY4 206 - -// -// aux keys are for multi-buttoned joysticks to generate so they can use -// the normal binding process -// -#define K_AUX1 207 -#define K_AUX2 208 -#define K_AUX3 209 -#define K_AUX4 210 -#define K_AUX5 211 -#define K_AUX6 212 -#define K_AUX7 213 -#define K_AUX8 214 -#define K_AUX9 215 -#define K_AUX10 216 -#define K_AUX11 217 -#define K_AUX12 218 -#define K_AUX13 219 -#define K_AUX14 220 -#define K_AUX15 221 -#define K_AUX16 222 -#define K_AUX17 223 -#define K_AUX18 224 -#define K_AUX19 225 -#define K_AUX20 226 -#define K_AUX21 227 -#define K_AUX22 228 -#define K_AUX23 229 -#define K_AUX24 230 -#define K_AUX25 231 -#define K_AUX26 232 -#define K_AUX27 233 -#define K_AUX28 234 -#define K_AUX29 235 -#define K_AUX30 236 -#define K_AUX31 237 -#define K_AUX32 238 - -// JACK: Intellimouse(c) Mouse Wheel Support - -#define K_MWHEELUP 239 -#define K_MWHEELDOWN 240 - - - -typedef enum {key_game, key_console, key_message, key_menu} keydest_t; - -extern keydest_t key_dest; -extern char *keybindings[256]; -extern int key_repeats[256]; -extern int key_count; // incremented every key event -extern int key_lastpress; - -void Key_Event (int key, qboolean down); -void Key_Init (void); -void Key_WriteBindings (FILE *f); -void Key_SetBinding (int keynum, char *binding); -void Key_ClearStates (void); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// these are the key numbers that should be passed to Key_Event +// +#define K_TAB 9 +#define K_ENTER 13 +#define K_ESCAPE 27 +#define K_SPACE 32 + +// normal keys should be passed as lowercased ascii + +#define K_BACKSPACE 127 +#define K_UPARROW 128 +#define K_DOWNARROW 129 +#define K_LEFTARROW 130 +#define K_RIGHTARROW 131 + +#define K_ALT 132 +#define K_CTRL 133 +#define K_SHIFT 134 +#define K_F1 135 +#define K_F2 136 +#define K_F3 137 +#define K_F4 138 +#define K_F5 139 +#define K_F6 140 +#define K_F7 141 +#define K_F8 142 +#define K_F9 143 +#define K_F10 144 +#define K_F11 145 +#define K_F12 146 +#define K_INS 147 +#define K_DEL 148 +#define K_PGDN 149 +#define K_PGUP 150 +#define K_HOME 151 +#define K_END 152 + +#define K_PAUSE 255 + +// +// mouse buttons generate virtual keys +// +#define K_MOUSE1 200 +#define K_MOUSE2 201 +#define K_MOUSE3 202 + +// +// joystick buttons +// +#define K_JOY1 203 +#define K_JOY2 204 +#define K_JOY3 205 +#define K_JOY4 206 + +// +// aux keys are for multi-buttoned joysticks to generate so they can use +// the normal binding process +// +#define K_AUX1 207 +#define K_AUX2 208 +#define K_AUX3 209 +#define K_AUX4 210 +#define K_AUX5 211 +#define K_AUX6 212 +#define K_AUX7 213 +#define K_AUX8 214 +#define K_AUX9 215 +#define K_AUX10 216 +#define K_AUX11 217 +#define K_AUX12 218 +#define K_AUX13 219 +#define K_AUX14 220 +#define K_AUX15 221 +#define K_AUX16 222 +#define K_AUX17 223 +#define K_AUX18 224 +#define K_AUX19 225 +#define K_AUX20 226 +#define K_AUX21 227 +#define K_AUX22 228 +#define K_AUX23 229 +#define K_AUX24 230 +#define K_AUX25 231 +#define K_AUX26 232 +#define K_AUX27 233 +#define K_AUX28 234 +#define K_AUX29 235 +#define K_AUX30 236 +#define K_AUX31 237 +#define K_AUX32 238 + +// JACK: Intellimouse(c) Mouse Wheel Support + +#define K_MWHEELUP 239 +#define K_MWHEELDOWN 240 + + + +typedef enum {key_game, key_console, key_message, key_menu} keydest_t; + +extern keydest_t key_dest; +extern char *keybindings[256]; +extern int key_repeats[256]; +extern int key_count; // incremented every key event +extern int key_lastpress; + +void Key_Event (int key, qboolean down); +void Key_Init (void); +void Key_WriteBindings (FILE *f); +void Key_SetBinding (int keynum, char *binding); +void Key_ClearStates (void); + diff --git a/WinQuake/kit/3DFX.TXT b/WinQuake/kit/3DFX.TXT index 283fdd3..6c0aa1d 100644 --- a/WinQuake/kit/3DFX.TXT +++ b/WinQuake/kit/3DFX.TXT @@ -1,279 +1,279 @@ -GLQuake Drivers for Voodoo Graphics Based 3D Accelerators -Preliminary Release 2 - -Copyright ( 1997 3Dfx Interactive, Inc. ) -All Rights Reserved - -3Dfx Interactive, Inc. -www: www.3dfx.com -news: news.3dfx.com - ------------------------------------------------------------------------ -NOTE: GLQuake requires DirectX 2.0 or DirectX 3.0 -(Needed for DirectSound support) - -DirectX 2.0 or DirectX 3.0 can be installed from the media provided -with your Voodoo Based 3D Accelerator. ------------------------------------------------------------------------ - - - -Release Notes for GLQuake Preliminary Release 2 (Quake Version 1.07) - ------------------------------------------------------------------------ -What's in the distribution? ------------------------------------------------------------------------ -This distribution contains GLQuake Drivers for Voodoo Graphics Based 3D -Accelerators. These drivers were tested on the following boards: - -- Diamond Monster 3D -- Orchid Righteous 3D -- 3Dfx Interactive reference boards - -NOTE: The enclosed drivers are not meant to replace any Direct3D or -Glide drivers provided by your Voodoo Graphics card manufacturer. -Please obtain supported drivers from: - -- Diamond supported drivers can be obtained from www.diamondmm.com -- Orchid supported drivers can be obtained from www.orchid.com - - -Included Files --------------- - -OPENGL32.DLL - QuakeGL Interface to Voodoo Graphics -FXMEMMAP.VXD - Voodoo Graphics VXD -GLQUAKE.EXE - ID Software provided GLQUAKE.EXE -README.TXT - ID Software provided README.TXT -READ3DFX.TXT - This File - -All enclosed files MUST reside in your Quake directory and not in the -Windows\SYSTEM directory. - -OEMSR2 users: Do NOT replace OPENGL32.DLL located in your -Windows\SYSTEM directory. - - - ------------------------------------------------------------------------ -Installation ------------------------------------------------------------------------ - -Requirements ------------- - -- Voodoo Graphics Based 3D Accelerator -- Windows 95 -- A PC with a Pentium 90 or higher CPU -- 16MB of RAM -- 2D Video card set at 16 bit or higher color - -Installation ------------- - -Adding GLQuake Driver Support ------------------------------ -1) Install the FULL Version (Not the Shareware version!) of Quake. - -2) Copy the GLQUAKE.EXE and other associated files from the GLQuake - ZIP file to your Quake Directory. (Use Windows Explorer) - -3) Copy the enclosed OPENGL32.DLL file to your Quake Directory. - (Use Windows Explorer) NOTE: DO NOT COPY OPENGL32.DLL to your - Windows\SYSTEM directory - -4) Create a Desktop Shortcut for GLQuake: Using the right mouse button - drag the GLQUAKE.EXE file from Windows Explorer to the Desktop. - When prompted choose "Create Shortcut" - -5) Create an autoexec.cfg file in the ID1\ directory of your quake - installation if you do not already have one. Add the line - - gl_playermip "2" - - to the file. - -6) Start GLQuake by running the shortcut. - - -Troubleshooting and Frequently Asked Questions ----------------------------------------------- - -1. Will GLQuake work with shareware Quake? - -No, the full registered version of Quake is required. - - - -2. Do I need any other drivers to run GLQuake on Voodoo Graphics? - -Just make sure that the FXMEMMAP.VXD file is in your Windows\SYSTEM -directory and that DirectX 2.0, DirectX 3.0 or DirectX 3.0a are -installed as GLQuake uses DirectSound. The latest version of DirectX -can be obtained from: - http://www.microsoft.com/mediadev/download/isdk.htm - - - -3. I installed GLQuake and try to run the GLQUAKE.EXE file but I get a -"no RGB fullscreen modes available" How do I get GLQuake to run? - -Make sure that your 2D video card is set to 16bit color (65K colors, -not 16 colors). In addition, do not start GLQuake from a full screen -MS-DOS prompt. - - - -4. GLQuake comes up for a little while then drops me back to the -Windows 95 desktop, what's wrong? - -Your Virtual Memory settings on your system should be increased. Open -Control Panel, System - click on the Performance tab and then click on -Virtual Memory. Adjust the settings so that the minimum swap file size -is 80MB. You may also want to delete all the mesh files - do this by -deleting the quake\ID1\glquake directory. - - - -5. Why does GLQuake try to connect to my Internet connection whenever -it starts? - -GLQuake uses Windows networking. Auto-Dial is likely enabled in your -Internet Control Panel or in Internet Explorer Options. Single -Player users: To disable Network use in GLQuake and prevent the -network connection screen from coming up, add "-nolan" to the -GLQUAKE.EXE command line, example: - GLQUAKE.EXE -nolan - - - - -6. I have a three button mouse, but I can't use or set the middle -button in GLQuake, what's wrong? - -To use a three button mouse with GLQuake, your Windows mouse driver -must support three buttons. Use the Logitech PS/2, Serial or Bus -driver instead of the Microsoft or Standard PS/2, Serial or Bus driver. -Also, make certain that your Mouse control panel sets the middle button -to "middle" and not "double click". - - - -7. Mouse input seems jumpy, how do I fix that? - -From the console (hit the ~ tilde key), enter m_filter 1 -This option can be added to the AUTOEXEC.CFG file (in the \ID1 -directory). You may also add this option to the GLQUAKE.EXE command -line, example: - GLQUAKE.EXE +m_filter 1 - - - -8. While playing GLQuake the sound stutters, how do I fix it? - -If your sound card does not support DirectSound, you may encounter -stuttering sound during game play. Try adding the following value to -the CONFIG.CFG file (in the quake\ID1 directory): - _snd_mixahead ".14" - - - -9. When I hit ALT-TAB or the Windows start button to switch to another -application why do I return to a 640x480 display? - -GLQuake by default needs to keep the 2D display at 640x480 while it is -running. To return the display to your normal setting you must exit -GLQuake. To prevent this, add the following to the GLQUAKE.EXE command -line options "+_windowed_mouse 1" and "-window" example: - GLQUAKE.EXE +_windowed_mouse 1 -window - - - -10. GLQuake multiplayer can't find other games or won't connect. - -GLQuake uses Windows 95 Networking. Verify that the correct networking -components are installed and that you can connect to the other machine -using File and print sharing or TCP/IP ping. If you are using IPX also -make certain that the frame type is the same on all the systems. - - - -11. GLQuake multiplayer slows down alot, how do I fix it? - -Add gl_playermip 2 to the AUTOEXEC.CFG file (in the \ID1 directory) -You may however add "+gl_playermip 2" to the GLQUAKE.EXE command line, -example: - GLQUAKE.EXE +gl_playermip 2 - - - -12. Does the Activision(r) Scourge of Armagon add-on (Mission Pack 1) -work with GLQuake? - -Yes, start GLQUAKE.EXE with a "-hipnotic" switch. Example: - GLQUAKE.EXE -hipnotic - - - -13. Do other 3rd party quake levels work with GLQuake? - -Not all 3rd party levels have been tested, some may not work properly -or optimally. - - - -14. Will GLQuake use a Voodoo Graphics accelerator under Windows NT? - -The 3Dfx GLQuake drivers currently only work under Windows 95. - - - -15. After installing GLQuake the OpenGL screen savers in Windows 95 -(OEMSR2) don't work. What's wrong? - -The OpenGL Windows 95 screen savers in OEMSR2 will fail if you copied -the OPENGL32.DLL file that comes with GLQuake to your Windows\SYSTEM -directory. The 3Dfx OPENGL32.DLL file only works with Quake. It will -not run with other OpenGL applications. If you copied the 3Dfx -OPENGL32.DLL to your Windows\SYSTEM directory and need to restore the -Microsoft provided OPENGL32.DLL, follow these steps: - - OEMSR2 Users - ------------ - 1) Insert your Windows 95 CD into your CD-ROM drive - 2) Open a MS-DOS prompt, (Click Start, Programs, MS-DOS Prompt) - 3) Switch to the Windows\SYSTEM directory, ie: - C: - CD\Windows\system - 4) At the command prompt, enter: - EXTRACT /A E:\WIN95 opengl32.dll - (Substitute E:\ for your CD-ROM drive letter) - - Standard Windows 95 Users - ------------------------- - 1) Download and reinstall OpenGL for Windows 95 from the source - you previously used. - - - -16. How do I get support for GLQuake - -GLQuake is currently unsupported. You may however find answers to -questions on various Quake dedicated websites. 3Dfx provides a GLQuake -newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to -discuss GLQuake with other users. 3Dfx also provides a regularly -updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html - - - -16. How do I send a bug report? - -If your problem is not resolved in this document or our updated FAQ -(please see #15) and your bug is related to visual quality, performance -or stability send an email to quake_bugs@3dfx.com - Describe your -system configuration (CPU Type, CPU Speed, 2D Video Card type, Amount -of Memory, Virtual Memory Size..etc.) and how to recreate the bug. - - -Voodoo Graphics is a trademark of 3Dfx Interactive, Inc. All other +GLQuake Drivers for Voodoo Graphics Based 3D Accelerators +Preliminary Release 2 + +Copyright ( 1997 3Dfx Interactive, Inc. ) +All Rights Reserved + +3Dfx Interactive, Inc. +www: www.3dfx.com +news: news.3dfx.com + +----------------------------------------------------------------------- +NOTE: GLQuake requires DirectX 2.0 or DirectX 3.0 +(Needed for DirectSound support) + +DirectX 2.0 or DirectX 3.0 can be installed from the media provided +with your Voodoo Based 3D Accelerator. +----------------------------------------------------------------------- + + + +Release Notes for GLQuake Preliminary Release 2 (Quake Version 1.07) + +----------------------------------------------------------------------- +What's in the distribution? +----------------------------------------------------------------------- +This distribution contains GLQuake Drivers for Voodoo Graphics Based 3D +Accelerators. These drivers were tested on the following boards: + +- Diamond Monster 3D +- Orchid Righteous 3D +- 3Dfx Interactive reference boards + +NOTE: The enclosed drivers are not meant to replace any Direct3D or +Glide drivers provided by your Voodoo Graphics card manufacturer. +Please obtain supported drivers from: + +- Diamond supported drivers can be obtained from www.diamondmm.com +- Orchid supported drivers can be obtained from www.orchid.com + + +Included Files +-------------- + +OPENGL32.DLL - QuakeGL Interface to Voodoo Graphics +FXMEMMAP.VXD - Voodoo Graphics VXD +GLQUAKE.EXE - ID Software provided GLQUAKE.EXE +README.TXT - ID Software provided README.TXT +READ3DFX.TXT - This File + +All enclosed files MUST reside in your Quake directory and not in the +Windows\SYSTEM directory. + +OEMSR2 users: Do NOT replace OPENGL32.DLL located in your +Windows\SYSTEM directory. + + + +----------------------------------------------------------------------- +Installation +----------------------------------------------------------------------- + +Requirements +------------ + +- Voodoo Graphics Based 3D Accelerator +- Windows 95 +- A PC with a Pentium 90 or higher CPU +- 16MB of RAM +- 2D Video card set at 16 bit or higher color + +Installation +------------ + +Adding GLQuake Driver Support +----------------------------- +1) Install the FULL Version (Not the Shareware version!) of Quake. + +2) Copy the GLQUAKE.EXE and other associated files from the GLQuake + ZIP file to your Quake Directory. (Use Windows Explorer) + +3) Copy the enclosed OPENGL32.DLL file to your Quake Directory. + (Use Windows Explorer) NOTE: DO NOT COPY OPENGL32.DLL to your + Windows\SYSTEM directory + +4) Create a Desktop Shortcut for GLQuake: Using the right mouse button + drag the GLQUAKE.EXE file from Windows Explorer to the Desktop. + When prompted choose "Create Shortcut" + +5) Create an autoexec.cfg file in the ID1\ directory of your quake + installation if you do not already have one. Add the line + + gl_playermip "2" + + to the file. + +6) Start GLQuake by running the shortcut. + + +Troubleshooting and Frequently Asked Questions +---------------------------------------------- + +1. Will GLQuake work with shareware Quake? + +No, the full registered version of Quake is required. + + + +2. Do I need any other drivers to run GLQuake on Voodoo Graphics? + +Just make sure that the FXMEMMAP.VXD file is in your Windows\SYSTEM +directory and that DirectX 2.0, DirectX 3.0 or DirectX 3.0a are +installed as GLQuake uses DirectSound. The latest version of DirectX +can be obtained from: + http://www.microsoft.com/mediadev/download/isdk.htm + + + +3. I installed GLQuake and try to run the GLQUAKE.EXE file but I get a +"no RGB fullscreen modes available" How do I get GLQuake to run? + +Make sure that your 2D video card is set to 16bit color (65K colors, +not 16 colors). In addition, do not start GLQuake from a full screen +MS-DOS prompt. + + + +4. GLQuake comes up for a little while then drops me back to the +Windows 95 desktop, what's wrong? + +Your Virtual Memory settings on your system should be increased. Open +Control Panel, System - click on the Performance tab and then click on +Virtual Memory. Adjust the settings so that the minimum swap file size +is 80MB. You may also want to delete all the mesh files - do this by +deleting the quake\ID1\glquake directory. + + + +5. Why does GLQuake try to connect to my Internet connection whenever +it starts? + +GLQuake uses Windows networking. Auto-Dial is likely enabled in your +Internet Control Panel or in Internet Explorer Options. Single +Player users: To disable Network use in GLQuake and prevent the +network connection screen from coming up, add "-nolan" to the +GLQUAKE.EXE command line, example: + GLQUAKE.EXE -nolan + + + + +6. I have a three button mouse, but I can't use or set the middle +button in GLQuake, what's wrong? + +To use a three button mouse with GLQuake, your Windows mouse driver +must support three buttons. Use the Logitech PS/2, Serial or Bus +driver instead of the Microsoft or Standard PS/2, Serial or Bus driver. +Also, make certain that your Mouse control panel sets the middle button +to "middle" and not "double click". + + + +7. Mouse input seems jumpy, how do I fix that? + +From the console (hit the ~ tilde key), enter m_filter 1 +This option can be added to the AUTOEXEC.CFG file (in the \ID1 +directory). You may also add this option to the GLQUAKE.EXE command +line, example: + GLQUAKE.EXE +m_filter 1 + + + +8. While playing GLQuake the sound stutters, how do I fix it? + +If your sound card does not support DirectSound, you may encounter +stuttering sound during game play. Try adding the following value to +the CONFIG.CFG file (in the quake\ID1 directory): + _snd_mixahead ".14" + + + +9. When I hit ALT-TAB or the Windows start button to switch to another +application why do I return to a 640x480 display? + +GLQuake by default needs to keep the 2D display at 640x480 while it is +running. To return the display to your normal setting you must exit +GLQuake. To prevent this, add the following to the GLQUAKE.EXE command +line options "+_windowed_mouse 1" and "-window" example: + GLQUAKE.EXE +_windowed_mouse 1 -window + + + +10. GLQuake multiplayer can't find other games or won't connect. + +GLQuake uses Windows 95 Networking. Verify that the correct networking +components are installed and that you can connect to the other machine +using File and print sharing or TCP/IP ping. If you are using IPX also +make certain that the frame type is the same on all the systems. + + + +11. GLQuake multiplayer slows down alot, how do I fix it? + +Add gl_playermip 2 to the AUTOEXEC.CFG file (in the \ID1 directory) +You may however add "+gl_playermip 2" to the GLQUAKE.EXE command line, +example: + GLQUAKE.EXE +gl_playermip 2 + + + +12. Does the Activision(r) Scourge of Armagon add-on (Mission Pack 1) +work with GLQuake? + +Yes, start GLQUAKE.EXE with a "-hipnotic" switch. Example: + GLQUAKE.EXE -hipnotic + + + +13. Do other 3rd party quake levels work with GLQuake? + +Not all 3rd party levels have been tested, some may not work properly +or optimally. + + + +14. Will GLQuake use a Voodoo Graphics accelerator under Windows NT? + +The 3Dfx GLQuake drivers currently only work under Windows 95. + + + +15. After installing GLQuake the OpenGL screen savers in Windows 95 +(OEMSR2) don't work. What's wrong? + +The OpenGL Windows 95 screen savers in OEMSR2 will fail if you copied +the OPENGL32.DLL file that comes with GLQuake to your Windows\SYSTEM +directory. The 3Dfx OPENGL32.DLL file only works with Quake. It will +not run with other OpenGL applications. If you copied the 3Dfx +OPENGL32.DLL to your Windows\SYSTEM directory and need to restore the +Microsoft provided OPENGL32.DLL, follow these steps: + + OEMSR2 Users + ------------ + 1) Insert your Windows 95 CD into your CD-ROM drive + 2) Open a MS-DOS prompt, (Click Start, Programs, MS-DOS Prompt) + 3) Switch to the Windows\SYSTEM directory, ie: + C: + CD\Windows\system + 4) At the command prompt, enter: + EXTRACT /A E:\WIN95 opengl32.dll + (Substitute E:\ for your CD-ROM drive letter) + + Standard Windows 95 Users + ------------------------- + 1) Download and reinstall OpenGL for Windows 95 from the source + you previously used. + + + +16. How do I get support for GLQuake + +GLQuake is currently unsupported. You may however find answers to +questions on various Quake dedicated websites. 3Dfx provides a GLQuake +newsgroup on news.3dfx.com (Newsgroup name is 3dfx.games.glquake ) to +discuss GLQuake with other users. 3Dfx also provides a regularly +updated GLQuake FAQ at: http://www.3dfx.com/game_dev/quake_faq.html + + + +16. How do I send a bug report? + +If your problem is not resolved in this document or our updated FAQ +(please see #15) and your bug is related to visual quality, performance +or stability send an email to quake_bugs@3dfx.com - Describe your +system configuration (CPU Type, CPU Speed, 2D Video Card type, Amount +of Memory, Virtual Memory Size..etc.) and how to recreate the bug. + + +Voodoo Graphics is a trademark of 3Dfx Interactive, Inc. All other trademarks are the property of their respective owners. \ No newline at end of file diff --git a/WinQuake/kit/JOYSTICK.TXT b/WinQuake/kit/JOYSTICK.TXT index 29dd305..7f919c9 100644 --- a/WinQuake/kit/JOYSTICK.TXT +++ b/WinQuake/kit/JOYSTICK.TXT @@ -2,166 +2,166 @@ NEW NOTE FOR 1.08: Joysticks are disabled by defualt now, due to problems on some systems without joysticks installed. Type "joystick 1" at the console, and everything will behave as documented here. This will be saved in your config file, so you will only have to do it once. -Description of Windows 95 Quake DirectInput support -By: FPgaming, Inc. (www.fpgaming.com) -- Creators of the Assassin 3D -File: JOYSTICK.TXT -Created: 02/21/97 -(This may be more information than you ever wanted to know.) - -The joystick support with Windows 95 Quake has been significantly enhanced. Standard joysticks, digital joysticks and new advanced controllers like the FPgaming Assassin 3D, the Logitech WingMan Warrior and the SpaceTec IMC SpaceOrb are all supported. - -To make it work, just verify that your joystick or game controller is selected in the Joystick control panel applet and has been calibrated and tested, then launch Windows 95 Quake (WinQuake.exe or glquake.exe). For standard and new digital joysticks, WinQuake will detect the joystick and automatically configure it. For advanced controllers, you will additionally need to run a config file (or run it from your autoexec.cfg) prior to the device operating. This will set the advanced features for your particular device. This config file should be obtained from your game controller company. The config files for the comman game controllers are included below. If you don't want your joystick or game controller enabled, add '-nojoy' to your command-line. - - -Standard Joystick Support -The standard joystick support has been enhanced to provide the following: -1. proportional movement (the farther you move the stick, the faster you move) -2. support for up to 32 buttons (JOY1-JOY4 and AUX5-AUX32) -3. sensitivity setting for each control (allows tuning and inverting the control direction) -4. dead-zone setting for each control - -The default joystick setting is for joystick left/right movement to control turning and for joystick forward/backward movement to control moving forward/backward. For optional strafing, add the 'sidestep' feature to one of your buttons (via the Customize menu). For optional looking, add the 'mouse look' feature to one of your buttons (also via the Customize menu). - -Additionally, there are several features that you can set from the Options menu. 'Always Run' allows you change your maximum speed from walking to running. 'Invert Mouse' allows you to change the direction the joystick has to move to when looking up and down. 'Lookspring' enables automatic look-forward-when-moving. And, 'Lookstrafe' automatically enables strafing when the 'mouse look' button is pressed. - -The following variables control your sensititivity settings: - joyforwardsensitivity - controls the ramp-up speed for moving forward and backward - joysidesensitivity - controls the ramp-up speed for moving side to side - joypitchsensitivity - controls the speed that you look up and down - joyyawsensitivity - controls the speed that you look left to right -You can set the sensitivity settings to negative numbers. This inverts the direction of movement for the control. The default sensitivity settings are 1 (or -1). There is no limit on the range; whatever feels good. - -The following variables control your threshold settings: - joyforwardthreshold - controls the dead-zone for moving forward and backward - joysidethreshold - controls the dead-zone for moving side to side - joypitchthreshold - controls the dead-zone for looking up and down - joyyawthreshold - controls the dead-zone for looking left and right -The threshold settings allow you to control your dead-zone (or no-movement zone). The default threshold settings are .15 (meaning 15% of the full-range). The range of the threshold settings is from 0 to 1. Troublesome analog joysticks may need a larger number (like .2). Premium joysticks can use a smaller number (like .1). - -The joystick sensitivity settings and the threshold settings are not saved after you quit your game as inadvertant settings can really hose your control. If you want to keep any changes, add them into your autoexec.cfg file. - -If your joystick has a POV hat, the buttons are mapped to AUX29-AUX32. So, you get 8 buttons with the Logitech WingMan Extreme and 12 buttons with the Microsoft SideWinder 3D Pro, etc. - - -Advanced Controller Support -The following features have been added: -1. support for all 6 axes (X, Y, Z, R, U, V) -2. mapping of any axis to any control (Forward, Look, Side, Turn) -3. proportional movement for all controls -4. sensitivity setting for any control (allows tuning and inverting the control direction) -5. threshold setting for any control (allows dead-zone setting) -6. support for absolute controls (like joysticks) and relative controls (like trackballs and spinners) -7. support for up to 32 buttons (JOY1-JOY4 and AUX5-AUX32) - -To make an advanced controller operate, you will need to get a config file from your game controller company. This file is typically placed in your quake\id1 directory and then it is called within your autoexec.cfg file. For example, if your config file is named gamectrl.cfg, place that file within your quake\id1 directory and add 'exec gamectrl.cfg' in your autoexec.cfg file. If you don't have an autoexec.cfg file, you can create one and just place this one line in it. - -****************************************************************************** -NOTE: The information below is for game controller companies to integrate their device and for anyone wanting to create a custom setup. - -In addition to the above new variables, there are six more for axis mapping. These are: - joyadvaxisx - controls mapping of DirectInput axis X (typically joystick left and right) - joyadvaxisy - controls mapping of DirectInput axis Y (typically joystick forward and backward) - joyadvaxisz - controls mapping of DirectInput axis Z (typically joystick throttle) - joyadvaxisr - controls mapping of DirectInput axis R (typically joystick rudder) - joyadvaxisu - controls mapping of DirectInput axis U (custom axis - Assassin 3D trackball left and right, WingMan Warrior SpinControl and SpaceOrb roll) - joyadvaxisv - controls mapping of DirectInput axis V (custom axis - Assassin 3D trackball forward and backward and SpaceOrb yaw) -Each joyadvaxis variable can be set to the following controls: - 0 = Axis not used - 1 = Axis is for forward and backward movement - 2 = Axis is for looking up and down (pitch) - 3 = Axis is for side to side movement - 4 = Axis is for turning left and right (yaw) -Additionally, each axis can be designated as an absolute axis (like a joystick) or a relative axis (like the FPgaming trackball or the WingMan Warrior SpinControl). Absolute axes are defined as having a stopping position whereas relative axes don't have a stopping position and just go around and around. To designate an axis as a relative axis, add 16 to the above control number. For example, to set the Assassin 3D's axis U to be looking left and right, type 'joyadvaxisu 20'. As another example, to make your rudder pedals contol turning left and right, type 'joyadvaxisr 4'. It's a bit complicated, but only needs to be done once. - -The advanced axes variables will not have any effect until joyadvanced is set to 1.0. Additionally, any changes to the to the axes will not take effect until the joyadvancedupdate command is executed. So, the procedure for creating an advanced mapping is: -1. set 'joyadvanced 1' -2. make any desired mapping changes -3. make any desired sensitivity changes -4. make any desired threshold changes -3. call 'joyadvancedupdate' - -Here is the config file for the FPgaming Assassin 3D: -// ADVA3D.CFG -// Revision 1.0 -- refer to www.fpgaming.com for updates -joyname "FPgaming Assassin 3D" -joyadvanced 1 -joyadvaxisx 3 -joyadvaxisy 1 -joyadvaxisz 0 -joyadvaxisr 0 -joyadvaxisu 20 -joyadvaxisv 18 -joyforwardsensitivity -1.0 -joysidesensitivity 1.0 -joypitchsensitivity -0.25 -joyyawsensitivity -0.5 -joyforwardthreshold 0.15 -joysidethreshold 0.15 -joyyawthreshold 0.0 -joypitchthreshold 0.0 -+mlook -joyadvancedupdate - -Here is a config file for the Logitech WingMan Warrior: -// ADVWW.CFG -// Revision 0.1 -- refer to www.logitech.com for updates -joyname "Logitech WingMan Warrior" -joyadvanced 1.0 -joywwhack1 1.0 -joywwhack2 1.0 -joyadvaxisx 3 -joyadvaxisy 1 -joyadvaxisz 0 -joyadvaxisr 0 -joyadvaxisu 20 -joyadvaxisv 0 -joyforwardsensitivity -1.0 -joysidesensitivity 1.0 -joypitchsensitivity 0.0 -joyyawsensitivity -0.6 -joyforwardthreshold 0.15 -joysidethreshold 0.15 -joypitchthreshold 0.0 -joyyawthreshold 0.0 -joyadvancedupdate - -Here is a config file for the SpaceTec IMC SpaceOrb: -// ADVSPORB.CFG -// Revision 0.1 -- refer to www.spacetec.com for updates -joyname "SpaceTec IMC SpaceOrb" -joyadvanced 1.0 -joyadvaxisx 3 -joyadvaxisy 1 -joyadvaxisz 0 -joyadvaxisr 2 -joyadvaxisu 0 -joyadvaxisv 4 -joyforwardsensitivity -1.0 -joysidesensitivity 1.0 -joypitchsensitivity -0.5 -joyyawsensitivity 1 -joyforwardthreshold 0.1 -joysidethreshold 0.1 -joypitchthreshold 0.1 -joyyawthreshold 0.1 -+mlook -joyadvancedupdate - -Here is a config file for making your joystick operate looking around and strafing, your rudder pedals control turning left and right and throttle control moving forward and backward: -joyname "Joystick, Rudder & Throttle" -joyadvanced 1.0 -joyadvaxisx 3 -joyadvaxisy 2 -joyadvaxisz 1 -joyadvaxisr 4 -joyadvaxisu 0 -joyadvaxisv 0 -joyforwardsensitivity -1.0 -joysidesensitivity -1.0 -joypitchsensitivity 1.0 -joyyawsensitivity -1.0 -joyforwardthreshold 0.15 -joysidethreshold 0.15 -joyyawthreshold 0.15 -joypitchthreshold 0.15 +Description of Windows 95 Quake DirectInput support +By: FPgaming, Inc. (www.fpgaming.com) -- Creators of the Assassin 3D +File: JOYSTICK.TXT +Created: 02/21/97 +(This may be more information than you ever wanted to know.) + +The joystick support with Windows 95 Quake has been significantly enhanced. Standard joysticks, digital joysticks and new advanced controllers like the FPgaming Assassin 3D, the Logitech WingMan Warrior and the SpaceTec IMC SpaceOrb are all supported. + +To make it work, just verify that your joystick or game controller is selected in the Joystick control panel applet and has been calibrated and tested, then launch Windows 95 Quake (WinQuake.exe or glquake.exe). For standard and new digital joysticks, WinQuake will detect the joystick and automatically configure it. For advanced controllers, you will additionally need to run a config file (or run it from your autoexec.cfg) prior to the device operating. This will set the advanced features for your particular device. This config file should be obtained from your game controller company. The config files for the comman game controllers are included below. If you don't want your joystick or game controller enabled, add '-nojoy' to your command-line. + + +Standard Joystick Support +The standard joystick support has been enhanced to provide the following: +1. proportional movement (the farther you move the stick, the faster you move) +2. support for up to 32 buttons (JOY1-JOY4 and AUX5-AUX32) +3. sensitivity setting for each control (allows tuning and inverting the control direction) +4. dead-zone setting for each control + +The default joystick setting is for joystick left/right movement to control turning and for joystick forward/backward movement to control moving forward/backward. For optional strafing, add the 'sidestep' feature to one of your buttons (via the Customize menu). For optional looking, add the 'mouse look' feature to one of your buttons (also via the Customize menu). + +Additionally, there are several features that you can set from the Options menu. 'Always Run' allows you change your maximum speed from walking to running. 'Invert Mouse' allows you to change the direction the joystick has to move to when looking up and down. 'Lookspring' enables automatic look-forward-when-moving. And, 'Lookstrafe' automatically enables strafing when the 'mouse look' button is pressed. + +The following variables control your sensititivity settings: + joyforwardsensitivity - controls the ramp-up speed for moving forward and backward + joysidesensitivity - controls the ramp-up speed for moving side to side + joypitchsensitivity - controls the speed that you look up and down + joyyawsensitivity - controls the speed that you look left to right +You can set the sensitivity settings to negative numbers. This inverts the direction of movement for the control. The default sensitivity settings are 1 (or -1). There is no limit on the range; whatever feels good. + +The following variables control your threshold settings: + joyforwardthreshold - controls the dead-zone for moving forward and backward + joysidethreshold - controls the dead-zone for moving side to side + joypitchthreshold - controls the dead-zone for looking up and down + joyyawthreshold - controls the dead-zone for looking left and right +The threshold settings allow you to control your dead-zone (or no-movement zone). The default threshold settings are .15 (meaning 15% of the full-range). The range of the threshold settings is from 0 to 1. Troublesome analog joysticks may need a larger number (like .2). Premium joysticks can use a smaller number (like .1). + +The joystick sensitivity settings and the threshold settings are not saved after you quit your game as inadvertant settings can really hose your control. If you want to keep any changes, add them into your autoexec.cfg file. + +If your joystick has a POV hat, the buttons are mapped to AUX29-AUX32. So, you get 8 buttons with the Logitech WingMan Extreme and 12 buttons with the Microsoft SideWinder 3D Pro, etc. + + +Advanced Controller Support +The following features have been added: +1. support for all 6 axes (X, Y, Z, R, U, V) +2. mapping of any axis to any control (Forward, Look, Side, Turn) +3. proportional movement for all controls +4. sensitivity setting for any control (allows tuning and inverting the control direction) +5. threshold setting for any control (allows dead-zone setting) +6. support for absolute controls (like joysticks) and relative controls (like trackballs and spinners) +7. support for up to 32 buttons (JOY1-JOY4 and AUX5-AUX32) + +To make an advanced controller operate, you will need to get a config file from your game controller company. This file is typically placed in your quake\id1 directory and then it is called within your autoexec.cfg file. For example, if your config file is named gamectrl.cfg, place that file within your quake\id1 directory and add 'exec gamectrl.cfg' in your autoexec.cfg file. If you don't have an autoexec.cfg file, you can create one and just place this one line in it. + +****************************************************************************** +NOTE: The information below is for game controller companies to integrate their device and for anyone wanting to create a custom setup. + +In addition to the above new variables, there are six more for axis mapping. These are: + joyadvaxisx - controls mapping of DirectInput axis X (typically joystick left and right) + joyadvaxisy - controls mapping of DirectInput axis Y (typically joystick forward and backward) + joyadvaxisz - controls mapping of DirectInput axis Z (typically joystick throttle) + joyadvaxisr - controls mapping of DirectInput axis R (typically joystick rudder) + joyadvaxisu - controls mapping of DirectInput axis U (custom axis - Assassin 3D trackball left and right, WingMan Warrior SpinControl and SpaceOrb roll) + joyadvaxisv - controls mapping of DirectInput axis V (custom axis - Assassin 3D trackball forward and backward and SpaceOrb yaw) +Each joyadvaxis variable can be set to the following controls: + 0 = Axis not used + 1 = Axis is for forward and backward movement + 2 = Axis is for looking up and down (pitch) + 3 = Axis is for side to side movement + 4 = Axis is for turning left and right (yaw) +Additionally, each axis can be designated as an absolute axis (like a joystick) or a relative axis (like the FPgaming trackball or the WingMan Warrior SpinControl). Absolute axes are defined as having a stopping position whereas relative axes don't have a stopping position and just go around and around. To designate an axis as a relative axis, add 16 to the above control number. For example, to set the Assassin 3D's axis U to be looking left and right, type 'joyadvaxisu 20'. As another example, to make your rudder pedals contol turning left and right, type 'joyadvaxisr 4'. It's a bit complicated, but only needs to be done once. + +The advanced axes variables will not have any effect until joyadvanced is set to 1.0. Additionally, any changes to the to the axes will not take effect until the joyadvancedupdate command is executed. So, the procedure for creating an advanced mapping is: +1. set 'joyadvanced 1' +2. make any desired mapping changes +3. make any desired sensitivity changes +4. make any desired threshold changes +3. call 'joyadvancedupdate' + +Here is the config file for the FPgaming Assassin 3D: +// ADVA3D.CFG +// Revision 1.0 -- refer to www.fpgaming.com for updates +joyname "FPgaming Assassin 3D" +joyadvanced 1 +joyadvaxisx 3 +joyadvaxisy 1 +joyadvaxisz 0 +joyadvaxisr 0 +joyadvaxisu 20 +joyadvaxisv 18 +joyforwardsensitivity -1.0 +joysidesensitivity 1.0 +joypitchsensitivity -0.25 +joyyawsensitivity -0.5 +joyforwardthreshold 0.15 +joysidethreshold 0.15 +joyyawthreshold 0.0 +joypitchthreshold 0.0 ++mlook +joyadvancedupdate + +Here is a config file for the Logitech WingMan Warrior: +// ADVWW.CFG +// Revision 0.1 -- refer to www.logitech.com for updates +joyname "Logitech WingMan Warrior" +joyadvanced 1.0 +joywwhack1 1.0 +joywwhack2 1.0 +joyadvaxisx 3 +joyadvaxisy 1 +joyadvaxisz 0 +joyadvaxisr 0 +joyadvaxisu 20 +joyadvaxisv 0 +joyforwardsensitivity -1.0 +joysidesensitivity 1.0 +joypitchsensitivity 0.0 +joyyawsensitivity -0.6 +joyforwardthreshold 0.15 +joysidethreshold 0.15 +joypitchthreshold 0.0 +joyyawthreshold 0.0 +joyadvancedupdate + +Here is a config file for the SpaceTec IMC SpaceOrb: +// ADVSPORB.CFG +// Revision 0.1 -- refer to www.spacetec.com for updates +joyname "SpaceTec IMC SpaceOrb" +joyadvanced 1.0 +joyadvaxisx 3 +joyadvaxisy 1 +joyadvaxisz 0 +joyadvaxisr 2 +joyadvaxisu 0 +joyadvaxisv 4 +joyforwardsensitivity -1.0 +joysidesensitivity 1.0 +joypitchsensitivity -0.5 +joyyawsensitivity 1 +joyforwardthreshold 0.1 +joysidethreshold 0.1 +joypitchthreshold 0.1 +joyyawthreshold 0.1 ++mlook +joyadvancedupdate + +Here is a config file for making your joystick operate looking around and strafing, your rudder pedals control turning left and right and throttle control moving forward and backward: +joyname "Joystick, Rudder & Throttle" +joyadvanced 1.0 +joyadvaxisx 3 +joyadvaxisy 2 +joyadvaxisz 1 +joyadvaxisr 4 +joyadvaxisu 0 +joyadvaxisv 0 +joyforwardsensitivity -1.0 +joysidesensitivity -1.0 +joypitchsensitivity 1.0 +joyyawsensitivity -1.0 +joyforwardthreshold 0.15 +joysidethreshold 0.15 +joyyawthreshold 0.15 +joypitchthreshold 0.15 joyadvancedupdate \ No newline at end of file diff --git a/WinQuake/kit/README.TXT b/WinQuake/kit/README.TXT index 5120943..b77c2ff 100644 --- a/WinQuake/kit/README.TXT +++ b/WinQuake/kit/README.TXT @@ -1,171 +1,171 @@ -Glquake v0.97, Quake v1.09 release notes - -3dfx owners -- read the 3dfx.txt file. - -On a standard OpenGL system, all you should need to do to run glquake is put -glquake.exe in your quake directory, and run it from there. DO NOT install -the opengl32.dll unless you have a 3dfx! Glquake should change the screen -resolution to 640*480*32k colors and run full screen by default. - -If you are running win-95, your desktop must be set to 32k or 64k colors -before running glquake. NT can switch automatically. - -Theoretically, glquake will run on any compliant OpenGL that supports the -texture objects extensions, but unless it is very powerfull hardware that -accelerates everything needed, the game play will not be acceptable. If it -has to go through any software emulation paths, the performance will likely -by well under one frame per second. - -3dfx has provided an opengl32.dll that implements everything glquake needs, -but it is not a full opengl implementation. Other opengl applications are -very unlikely to work with it, so consider it basically a "glquake driver". -See the encluded 3dfx.txt for specific instalation notes. 3dfx can only run -full screen, but you must still have your desktop set to a 16 bit color mode -for glquake to start. - -resolution options ------------------- -We had dynamic resolution changing in glquake for a while, but every single -opengl driver I tried it on messed up in one way or another, so it is now -limited to startup time only. - -glquake -window -This will start glquake in a window on your desktop instead of switching the -screen to lower resolution and covering everything. - -glquake -width 800 -height 600 -Tries to run glquake at the specified resolution. Combined with -window, it -creates a desktop window that size, otherwise it tries to set a full screen -resolution. - -You can also specify the resolution of the console independant of the screen -resolution. - -glquake -conwidth 320 -This will specify a console resolution of 320 by 240 (the height is -automatically determined by the default 4:3 aspect ratio, you can also -specify the height directly with -conheight). - -In higher resolution modes such as 800x600 and 1024x768, glquake will default -to a 640x480 console, since the font becomes small enough at higher -resolutions to become unreadable. If do you wish to have a higher resolution -console and status bar, specify it as well, such as: -glquake -width 800 -height 600 -conwidth 800 - -texture options ---------------- -The amount of textures used in the game can have a large impact on performance. -There are several options that let you trade off visual quality for better -performance. - -There is no way to flush already loaded textures, so it is best to change -these options on the command line, or they will only take effect on some of -the textures when you change levels. - -OpenGL only allows textures to repeat on power of two boundaries (32, 64, -128, etc), but software quake had a number of textures that repeated at 24 -or 96 pixel boundaries. These need to be either stretched out to the next -higher size, or shrunk down to the next lower. By default, they are filtered -down to the smaller size, but you can cause it to use the larger size if you -really want by using: - -glquake +gl_round_down 0 -This will generally run well on a normal 4 MB 3dfx card, but for other cards -that have either worse texture management or slower texture swapping speeds, -there are some additional settings that can drastically lower the amount of -textures to be managed. - -glquake +gl_picmip 1 -This causes all textures to have one half the dimensions they otherwise would. -This makes them blurry, but very small. You can set this to 2 to make the -textures one quarter the resolution on each axis for REALLY blurry textures. - -glquake +gl_playermip 1 -This is similar to picmip, but is only used for other players in deathmatch. -Each player in a deathmatch requires an individual skin texture, so this can -be a serious problem for texture management. It wouldn't be unreasonable to -set this to 2 or even 3 if you are playing competatively (and don't care if -the other guys have smudged skins). If you change this during the game, it -will take effect as soon as a player changes their skin colors. - -GLQuake also supports the following extensions for faster texture operation: - -GL_SGIS_multitexture -Multitextures support allows certain hardware to render the world in one -pass instead of two. GLQuake uses two passes, one for the world textures -and the second for the lightmaps that are blended on the textures. On some -hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this -can be done in one pass. On hardware that supports this, you will get a -60% to 100% increase in frame rate. Currently, only 3DFX dual TMU cards -(such as the Obsidian 2220) support this extension, but other hardware will -soon follow. - -This extension will be autodetected and used. If for some reason it is not -working correctly, specify the command line option "-nomtex" to disable it. - -GL_EXT_shared_texture_palette -GLQuake uses 16bit textures by default but on OpenGL implementations -that support the GL_EXT_shared_texture_palette extension, GLQuake will use -8bit textures instead. This results in using half the needed texture memory -of 16bit texture and can improve performance. This is very little difference -in visual quality due to the fact that the textures are 8bit sources to -begin with. - -run time options ----------------- -At the console, you can set these values to effect drawing. - -gl_texturemode GL_NEAREST -Sets texture mapping to point sampled, which may be faster on some GL systems -(not on 3dfx). - -gl_texturemode GL_LINEAR_MIPMAP -This is the default texture mode. - -gl_texturemode GL_LINEAR_MIPMAP_LINEAR -This is the highest quality texture mapping (trilinear), but only very high -end hardware (intergraph intense 3D / realizm) supports it. Not that big of -a deal, actually. - -gl_finish 0 -This causes the game to not issue a glFinish() call each frame, which may make -some hardware run faster. If this is cleared, the 3dfx will back up a number -of frames and not be very playable. - -gl_flashblend 0 -By default, glquake just draws a shaded ball around objects that are emiting -light. Clearing this variable will cause it to properly relight the world -like normal quake, but it can be a significant speed hit on some systems. - -gl_ztrick 0 -Glquake uses a buffering method that avoids clearing the Z buffer, but some -hardware platforms don't like it. If the status bar and console are flashing -every other frame, clear this variable. - -gl_keeptjunctions 0 -If you clear this, glquake will remove colinear vertexes when it reloads the -level. This can give a few percent speedup, but it can leave a couple stray -blinking pixels on the screen. - -novelty features ----------------- -These are some rendering tricks that were easy to do in glquake. They aren't -very robust, but they are pretty cool to look at. - -r_shadows 1 -This causes every object to cast a shadow. - -r_wateralpha 0.7 -This sets the opacity of water textures, so you can see through it in properly -processed maps. 0.3 is very faint, almost like fog. 1 is completely solid -(the default). Unfortunately, the standard quake maps don't contain any -visibility information for seeing past water surfaces, so you can't just play -quake with this turned on. If you just want to see what it looks like, you -can set "r_novis 1", but that will make things go very slow. When I get a -chance, I will probably release some maps that have been processed properly -for this. - -r_mirroralpha 0.3 -This changes one particular texture (the stained glass texture in the EASY -start hall) into a mirror. The value is the opacity of the mirror surface. - +Glquake v0.97, Quake v1.09 release notes + +3dfx owners -- read the 3dfx.txt file. + +On a standard OpenGL system, all you should need to do to run glquake is put +glquake.exe in your quake directory, and run it from there. DO NOT install +the opengl32.dll unless you have a 3dfx! Glquake should change the screen +resolution to 640*480*32k colors and run full screen by default. + +If you are running win-95, your desktop must be set to 32k or 64k colors +before running glquake. NT can switch automatically. + +Theoretically, glquake will run on any compliant OpenGL that supports the +texture objects extensions, but unless it is very powerfull hardware that +accelerates everything needed, the game play will not be acceptable. If it +has to go through any software emulation paths, the performance will likely +by well under one frame per second. + +3dfx has provided an opengl32.dll that implements everything glquake needs, +but it is not a full opengl implementation. Other opengl applications are +very unlikely to work with it, so consider it basically a "glquake driver". +See the encluded 3dfx.txt for specific instalation notes. 3dfx can only run +full screen, but you must still have your desktop set to a 16 bit color mode +for glquake to start. + +resolution options +------------------ +We had dynamic resolution changing in glquake for a while, but every single +opengl driver I tried it on messed up in one way or another, so it is now +limited to startup time only. + +glquake -window +This will start glquake in a window on your desktop instead of switching the +screen to lower resolution and covering everything. + +glquake -width 800 -height 600 +Tries to run glquake at the specified resolution. Combined with -window, it +creates a desktop window that size, otherwise it tries to set a full screen +resolution. + +You can also specify the resolution of the console independant of the screen +resolution. + +glquake -conwidth 320 +This will specify a console resolution of 320 by 240 (the height is +automatically determined by the default 4:3 aspect ratio, you can also +specify the height directly with -conheight). + +In higher resolution modes such as 800x600 and 1024x768, glquake will default +to a 640x480 console, since the font becomes small enough at higher +resolutions to become unreadable. If do you wish to have a higher resolution +console and status bar, specify it as well, such as: +glquake -width 800 -height 600 -conwidth 800 + +texture options +--------------- +The amount of textures used in the game can have a large impact on performance. +There are several options that let you trade off visual quality for better +performance. + +There is no way to flush already loaded textures, so it is best to change +these options on the command line, or they will only take effect on some of +the textures when you change levels. + +OpenGL only allows textures to repeat on power of two boundaries (32, 64, +128, etc), but software quake had a number of textures that repeated at 24 +or 96 pixel boundaries. These need to be either stretched out to the next +higher size, or shrunk down to the next lower. By default, they are filtered +down to the smaller size, but you can cause it to use the larger size if you +really want by using: + +glquake +gl_round_down 0 +This will generally run well on a normal 4 MB 3dfx card, but for other cards +that have either worse texture management or slower texture swapping speeds, +there are some additional settings that can drastically lower the amount of +textures to be managed. + +glquake +gl_picmip 1 +This causes all textures to have one half the dimensions they otherwise would. +This makes them blurry, but very small. You can set this to 2 to make the +textures one quarter the resolution on each axis for REALLY blurry textures. + +glquake +gl_playermip 1 +This is similar to picmip, but is only used for other players in deathmatch. +Each player in a deathmatch requires an individual skin texture, so this can +be a serious problem for texture management. It wouldn't be unreasonable to +set this to 2 or even 3 if you are playing competatively (and don't care if +the other guys have smudged skins). If you change this during the game, it +will take effect as soon as a player changes their skin colors. + +GLQuake also supports the following extensions for faster texture operation: + +GL_SGIS_multitexture +Multitextures support allows certain hardware to render the world in one +pass instead of two. GLQuake uses two passes, one for the world textures +and the second for the lightmaps that are blended on the textures. On some +hardware, with a GL_SIGS_multitexture supported OpenGL implementation, this +can be done in one pass. On hardware that supports this, you will get a +60% to 100% increase in frame rate. Currently, only 3DFX dual TMU cards +(such as the Obsidian 2220) support this extension, but other hardware will +soon follow. + +This extension will be autodetected and used. If for some reason it is not +working correctly, specify the command line option "-nomtex" to disable it. + +GL_EXT_shared_texture_palette +GLQuake uses 16bit textures by default but on OpenGL implementations +that support the GL_EXT_shared_texture_palette extension, GLQuake will use +8bit textures instead. This results in using half the needed texture memory +of 16bit texture and can improve performance. This is very little difference +in visual quality due to the fact that the textures are 8bit sources to +begin with. + +run time options +---------------- +At the console, you can set these values to effect drawing. + +gl_texturemode GL_NEAREST +Sets texture mapping to point sampled, which may be faster on some GL systems +(not on 3dfx). + +gl_texturemode GL_LINEAR_MIPMAP +This is the default texture mode. + +gl_texturemode GL_LINEAR_MIPMAP_LINEAR +This is the highest quality texture mapping (trilinear), but only very high +end hardware (intergraph intense 3D / realizm) supports it. Not that big of +a deal, actually. + +gl_finish 0 +This causes the game to not issue a glFinish() call each frame, which may make +some hardware run faster. If this is cleared, the 3dfx will back up a number +of frames and not be very playable. + +gl_flashblend 0 +By default, glquake just draws a shaded ball around objects that are emiting +light. Clearing this variable will cause it to properly relight the world +like normal quake, but it can be a significant speed hit on some systems. + +gl_ztrick 0 +Glquake uses a buffering method that avoids clearing the Z buffer, but some +hardware platforms don't like it. If the status bar and console are flashing +every other frame, clear this variable. + +gl_keeptjunctions 0 +If you clear this, glquake will remove colinear vertexes when it reloads the +level. This can give a few percent speedup, but it can leave a couple stray +blinking pixels on the screen. + +novelty features +---------------- +These are some rendering tricks that were easy to do in glquake. They aren't +very robust, but they are pretty cool to look at. + +r_shadows 1 +This causes every object to cast a shadow. + +r_wateralpha 0.7 +This sets the opacity of water textures, so you can see through it in properly +processed maps. 0.3 is very faint, almost like fog. 1 is completely solid +(the default). Unfortunately, the standard quake maps don't contain any +visibility information for seeing past water surfaces, so you can't just play +quake with this turned on. If you just want to see what it looks like, you +can set "r_novis 1", but that will make things go very slow. When I get a +chance, I will probably release some maps that have been processed properly +for this. + +r_mirroralpha 0.3 +This changes one particular texture (the stained glass texture in the EASY +start hall) into a mirror. The value is the opacity of the mirror surface. + diff --git a/WinQuake/makezip.bat b/WinQuake/makezip.bat index 9686953..62d3084 100644 --- a/WinQuake/makezip.bat +++ b/WinQuake/makezip.bat @@ -1 +1 @@ -zip -9 -r code * -x *.obj -x *.sbr -x *.pch -x *.pdb -x *.o -x *.exe -x *.dll -x *.map -x *.bsc -x *.lib -x *.ilk -x *.exp -x *.idb -x *.zip +zip -9 -r code * -x *.obj -x *.sbr -x *.pch -x *.pdb -x *.o -x *.exe -x *.dll -x *.map -x *.bsc -x *.lib -x *.ilk -x *.exp -x *.idb -x *.zip diff --git a/WinQuake/math.s b/WinQuake/math.s index 00fcd09..bd68398 100644 --- a/WinQuake/math.s +++ b/WinQuake/math.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // math.s // x86 assembly-language math routines. diff --git a/WinQuake/mathlib.c b/WinQuake/mathlib.c index 9f5d644..cf8c672 100644 --- a/WinQuake/mathlib.c +++ b/WinQuake/mathlib.c @@ -1,585 +1,585 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// mathlib.c -- math primitives - -#include -#include "quakedef.h" - -void Sys_Error (char *error, ...); - -vec3_t vec3_origin = {0,0,0}; -int nanmask = 255<<23; - -/*-----------------------------------------------------------------*/ - -#define DEG2RAD( a ) ( a * M_PI ) / 180.0F - -void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) -{ - float d; - vec3_t n; - float inv_denom; - - inv_denom = 1.0F / DotProduct( normal, normal ); - - d = DotProduct( normal, p ) * inv_denom; - - n[0] = normal[0] * inv_denom; - n[1] = normal[1] * inv_denom; - n[2] = normal[2] * inv_denom; - - dst[0] = p[0] - d * n[0]; - dst[1] = p[1] - d * n[1]; - dst[2] = p[2] - d * n[2]; -} - -/* -** assumes "src" is normalized -*/ -void PerpendicularVector( vec3_t dst, const vec3_t src ) -{ - int pos; - int i; - float minelem = 1.0F; - vec3_t tempvec; - - /* - ** find the smallest magnitude axially aligned vector - */ - for ( pos = 0, i = 0; i < 3; i++ ) - { - if ( fabs( src[i] ) < minelem ) - { - pos = i; - minelem = fabs( src[i] ); - } - } - tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; - tempvec[pos] = 1.0F; - - /* - ** project the point onto the plane defined by src - */ - ProjectPointOnPlane( dst, tempvec, src ); - - /* - ** normalize the result - */ - VectorNormalize( dst ); -} - -#ifdef _WIN32 -#pragma optimize( "", off ) -#endif - - -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) -{ - float m[3][3]; - float im[3][3]; - float zrot[3][3]; - float tmpmat[3][3]; - float rot[3][3]; - int i; - vec3_t vr, vup, vf; - - vf[0] = dir[0]; - vf[1] = dir[1]; - vf[2] = dir[2]; - - PerpendicularVector( vr, dir ); - CrossProduct( vr, vf, vup ); - - m[0][0] = vr[0]; - m[1][0] = vr[1]; - m[2][0] = vr[2]; - - m[0][1] = vup[0]; - m[1][1] = vup[1]; - m[2][1] = vup[2]; - - m[0][2] = vf[0]; - m[1][2] = vf[1]; - m[2][2] = vf[2]; - - memcpy( im, m, sizeof( im ) ); - - im[0][1] = m[1][0]; - im[0][2] = m[2][0]; - im[1][0] = m[0][1]; - im[1][2] = m[2][1]; - im[2][0] = m[0][2]; - im[2][1] = m[1][2]; - - memset( zrot, 0, sizeof( zrot ) ); - zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; - - zrot[0][0] = cos( DEG2RAD( degrees ) ); - zrot[0][1] = sin( DEG2RAD( degrees ) ); - zrot[1][0] = -sin( DEG2RAD( degrees ) ); - zrot[1][1] = cos( DEG2RAD( degrees ) ); - - R_ConcatRotations( m, zrot, tmpmat ); - R_ConcatRotations( tmpmat, im, rot ); - - for ( i = 0; i < 3; i++ ) - { - dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; - } -} - -#ifdef _WIN32 -#pragma optimize( "", on ) -#endif - -/*-----------------------------------------------------------------*/ - - -float anglemod(float a) -{ -#if 0 - if (a >= 0) - a -= 360*(int)(a/360); - else - a += 360*( 1 + (int)(-a/360) ); -#endif - a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); - return a; -} - -/* -================== -BOPS_Error - -Split out like this for ASM to call. -================== -*/ -void BOPS_Error (void) -{ - Sys_Error ("BoxOnPlaneSide: Bad signbits"); -} - - -#if !id386 - -/* -================== -BoxOnPlaneSide - -Returns 1, 2, or 1 + 2 -================== -*/ -int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p) -{ - float dist1, dist2; - int sides; - -#if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this - // function -// fast axial cases - if (p->type < 3) - { - if (p->dist <= emins[p->type]) - return 1; - if (p->dist >= emaxs[p->type]) - return 2; - return 3; - } -#endif - -// general case - switch (p->signbits) - { - case 0: -dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; -dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - break; - case 1: -dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; -dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - break; - case 2: -dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; -dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - break; - case 3: -dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; -dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - break; - case 4: -dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; -dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - break; - case 5: -dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; -dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - break; - case 6: -dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; -dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - break; - case 7: -dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; -dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - break; - default: - dist1 = dist2 = 0; // shut up compiler - BOPS_Error (); - break; - } - -#if 0 - int i; - vec3_t corners[2]; - - for (i=0 ; i<3 ; i++) - { - if (plane->normal[i] < 0) - { - corners[0][i] = emins[i]; - corners[1][i] = emaxs[i]; - } - else - { - corners[1][i] = emins[i]; - corners[0][i] = emaxs[i]; - } - } - dist = DotProduct (plane->normal, corners[0]) - plane->dist; - dist2 = DotProduct (plane->normal, corners[1]) - plane->dist; - sides = 0; - if (dist1 >= 0) - sides = 1; - if (dist2 < 0) - sides |= 2; - -#endif - - sides = 0; - if (dist1 >= p->dist) - sides = 1; - if (dist2 < p->dist) - sides |= 2; - -#ifdef PARANOID -if (sides == 0) - Sys_Error ("BoxOnPlaneSide: sides==0"); -#endif - - return sides; -} - -#endif - - -void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - forward[0] = cp*cy; - forward[1] = cp*sy; - forward[2] = -sp; - right[0] = (-1*sr*sp*cy+-1*cr*-sy); - right[1] = (-1*sr*sp*sy+-1*cr*cy); - right[2] = -1*sr*cp; - up[0] = (cr*sp*cy+-sr*-sy); - up[1] = (cr*sp*sy+-sr*cy); - up[2] = cr*cp; -} - -int VectorCompare (vec3_t v1, vec3_t v2) -{ - int i; - - for (i=0 ; i<3 ; i++) - if (v1[i] != v2[i]) - return 0; - - return 1; -} - -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) -{ - vecc[0] = veca[0] + scale*vecb[0]; - vecc[1] = veca[1] + scale*vecb[1]; - vecc[2] = veca[2] + scale*vecb[2]; -} - - -vec_t _DotProduct (vec3_t v1, vec3_t v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) -{ - out[0] = veca[0]-vecb[0]; - out[1] = veca[1]-vecb[1]; - out[2] = veca[2]-vecb[2]; -} - -void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) -{ - out[0] = veca[0]+vecb[0]; - out[1] = veca[1]+vecb[1]; - out[2] = veca[2]+vecb[2]; -} - -void _VectorCopy (vec3_t in, vec3_t out) -{ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; -} - -void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) -{ - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -double sqrt(double x); - -vec_t Length(vec3_t v) -{ - int i; - float length; - - length = 0; - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); // FIXME - - return length; -} - -float VectorNormalize (vec3_t v) -{ - float length, ilength; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrt (length); // FIXME - - if (length) - { - ilength = 1/length; - v[0] *= ilength; - v[1] *= ilength; - v[2] *= ilength; - } - - return length; - -} - -void VectorInverse (vec3_t v) -{ - v[0] = -v[0]; - v[1] = -v[1]; - v[2] = -v[2]; -} - -void VectorScale (vec3_t in, vec_t scale, vec3_t out) -{ - out[0] = in[0]*scale; - out[1] = in[1]*scale; - out[2] = in[2]*scale; -} - - -int Q_log2(int val) -{ - int answer=0; - while (val>>=1) - answer++; - return answer; -} - - -/* -================ -R_ConcatRotations -================ -*/ -void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) -{ - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; -} - - -/* -================ -R_ConcatTransforms -================ -*/ -void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) -{ - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + - in1[0][2] * in2[2][3] + in1[0][3]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + - in1[1][2] * in2[2][3] + in1[1][3]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; - out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + - in1[2][2] * in2[2][3] + in1[2][3]; -} - - -/* -=================== -FloorDivMod - -Returns mathematically correct (floor-based) quotient and remainder for -numer and denom, both of which should contain no fractional part. The -quotient must fit in 32 bits. -==================== -*/ - -void FloorDivMod (double numer, double denom, int *quotient, - int *rem) -{ - int q, r; - double x; - -#ifndef PARANOID - if (denom <= 0.0) - Sys_Error ("FloorDivMod: bad denominator %d\n", denom); - -// if ((floor(numer) != numer) || (floor(denom) != denom)) -// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n", -// numer, denom); -#endif - - if (numer >= 0.0) - { - - x = floor(numer / denom); - q = (int)x; - r = (int)floor(numer - (x * denom)); - } - else - { - // - // perform operations with positive values, and fix mod to make floor-based - // - x = floor(-numer / denom); - q = -(int)x; - r = (int)floor(-numer - (x * denom)); - if (r != 0) - { - q--; - r = (int)denom - r; - } - } - - *quotient = q; - *rem = r; -} - - -/* -=================== -GreatestCommonDivisor -==================== -*/ -int GreatestCommonDivisor (int i1, int i2) -{ - if (i1 > i2) - { - if (i2 == 0) - return (i1); - return GreatestCommonDivisor (i2, i1 % i2); - } - else - { - if (i1 == 0) - return (i2); - return GreatestCommonDivisor (i1, i2 % i1); - } -} - - -#if !id386 - -// TODO: move to nonintel.c - -/* -=================== -Invert24To16 - -Inverts an 8.24 value to a 16.16 value -==================== -*/ - -fixed16_t Invert24To16(fixed16_t val) -{ - if (val < 256) - return (0xFFFFFFFF); - - return (fixed16_t) - (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5); -} - -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// mathlib.c -- math primitives + +#include +#include "quakedef.h" + +void Sys_Error (char *error, ...); + +vec3_t vec3_origin = {0,0,0}; +int nanmask = 255<<23; + +/*-----------------------------------------------------------------*/ + +#define DEG2RAD( a ) ( a * M_PI ) / 180.0F + +void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) +{ + float d; + vec3_t n; + float inv_denom; + + inv_denom = 1.0F / DotProduct( normal, normal ); + + d = DotProduct( normal, p ) * inv_denom; + + n[0] = normal[0] * inv_denom; + n[1] = normal[1] * inv_denom; + n[2] = normal[2] * inv_denom; + + dst[0] = p[0] - d * n[0]; + dst[1] = p[1] - d * n[1]; + dst[2] = p[2] - d * n[2]; +} + +/* +** assumes "src" is normalized +*/ +void PerpendicularVector( vec3_t dst, const vec3_t src ) +{ + int pos; + int i; + float minelem = 1.0F; + vec3_t tempvec; + + /* + ** find the smallest magnitude axially aligned vector + */ + for ( pos = 0, i = 0; i < 3; i++ ) + { + if ( fabs( src[i] ) < minelem ) + { + pos = i; + minelem = fabs( src[i] ); + } + } + tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; + tempvec[pos] = 1.0F; + + /* + ** project the point onto the plane defined by src + */ + ProjectPointOnPlane( dst, tempvec, src ); + + /* + ** normalize the result + */ + VectorNormalize( dst ); +} + +#ifdef _WIN32 +#pragma optimize( "", off ) +#endif + + +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) +{ + float m[3][3]; + float im[3][3]; + float zrot[3][3]; + float tmpmat[3][3]; + float rot[3][3]; + int i; + vec3_t vr, vup, vf; + + vf[0] = dir[0]; + vf[1] = dir[1]; + vf[2] = dir[2]; + + PerpendicularVector( vr, dir ); + CrossProduct( vr, vf, vup ); + + m[0][0] = vr[0]; + m[1][0] = vr[1]; + m[2][0] = vr[2]; + + m[0][1] = vup[0]; + m[1][1] = vup[1]; + m[2][1] = vup[2]; + + m[0][2] = vf[0]; + m[1][2] = vf[1]; + m[2][2] = vf[2]; + + memcpy( im, m, sizeof( im ) ); + + im[0][1] = m[1][0]; + im[0][2] = m[2][0]; + im[1][0] = m[0][1]; + im[1][2] = m[2][1]; + im[2][0] = m[0][2]; + im[2][1] = m[1][2]; + + memset( zrot, 0, sizeof( zrot ) ); + zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; + + zrot[0][0] = cos( DEG2RAD( degrees ) ); + zrot[0][1] = sin( DEG2RAD( degrees ) ); + zrot[1][0] = -sin( DEG2RAD( degrees ) ); + zrot[1][1] = cos( DEG2RAD( degrees ) ); + + R_ConcatRotations( m, zrot, tmpmat ); + R_ConcatRotations( tmpmat, im, rot ); + + for ( i = 0; i < 3; i++ ) + { + dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; + } +} + +#ifdef _WIN32 +#pragma optimize( "", on ) +#endif + +/*-----------------------------------------------------------------*/ + + +float anglemod(float a) +{ +#if 0 + if (a >= 0) + a -= 360*(int)(a/360); + else + a += 360*( 1 + (int)(-a/360) ); +#endif + a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); + return a; +} + +/* +================== +BOPS_Error + +Split out like this for ASM to call. +================== +*/ +void BOPS_Error (void) +{ + Sys_Error ("BoxOnPlaneSide: Bad signbits"); +} + + +#if !id386 + +/* +================== +BoxOnPlaneSide + +Returns 1, 2, or 1 + 2 +================== +*/ +int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p) +{ + float dist1, dist2; + int sides; + +#if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this + // function +// fast axial cases + if (p->type < 3) + { + if (p->dist <= emins[p->type]) + return 1; + if (p->dist >= emaxs[p->type]) + return 2; + return 3; + } +#endif + +// general case + switch (p->signbits) + { + case 0: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; + break; + case 1: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; + break; + case 2: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; + break; + case 3: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; + break; + case 4: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; + break; + case 5: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; + break; + case 6: +dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; + break; + case 7: +dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; + break; + default: + dist1 = dist2 = 0; // shut up compiler + BOPS_Error (); + break; + } + +#if 0 + int i; + vec3_t corners[2]; + + for (i=0 ; i<3 ; i++) + { + if (plane->normal[i] < 0) + { + corners[0][i] = emins[i]; + corners[1][i] = emaxs[i]; + } + else + { + corners[1][i] = emins[i]; + corners[0][i] = emaxs[i]; + } + } + dist = DotProduct (plane->normal, corners[0]) - plane->dist; + dist2 = DotProduct (plane->normal, corners[1]) - plane->dist; + sides = 0; + if (dist1 >= 0) + sides = 1; + if (dist2 < 0) + sides |= 2; + +#endif + + sides = 0; + if (dist1 >= p->dist) + sides = 1; + if (dist2 < p->dist) + sides |= 2; + +#ifdef PARANOID +if (sides == 0) + Sys_Error ("BoxOnPlaneSide: sides==0"); +#endif + + return sides; +} + +#endif + + +void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + forward[0] = cp*cy; + forward[1] = cp*sy; + forward[2] = -sp; + right[0] = (-1*sr*sp*cy+-1*cr*-sy); + right[1] = (-1*sr*sp*sy+-1*cr*cy); + right[2] = -1*sr*cp; + up[0] = (cr*sp*cy+-sr*-sy); + up[1] = (cr*sp*sy+-sr*cy); + up[2] = cr*cp; +} + +int VectorCompare (vec3_t v1, vec3_t v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (v1[i] != v2[i]) + return 0; + + return 1; +} + +void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) +{ + vecc[0] = veca[0] + scale*vecb[0]; + vecc[1] = veca[1] + scale*vecb[1]; + vecc[2] = veca[2] + scale*vecb[2]; +} + + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]-vecb[0]; + out[1] = veca[1]-vecb[1]; + out[2] = veca[2]-vecb[2]; +} + +void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]+vecb[0]; + out[1] = veca[1]+vecb[1]; + out[2] = veca[2]+vecb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +double sqrt(double x); + +vec_t Length(vec3_t v) +{ + int i; + float length; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); // FIXME + + return length; +} + +float VectorNormalize (vec3_t v) +{ + float length, ilength; + + length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + length = sqrt (length); // FIXME + + if (length) + { + ilength = 1/length; + v[0] *= ilength; + v[1] *= ilength; + v[2] *= ilength; + } + + return length; + +} + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void VectorScale (vec3_t in, vec_t scale, vec3_t out) +{ + out[0] = in[0]*scale; + out[1] = in[1]*scale; + out[2] = in[2]*scale; +} + + +int Q_log2(int val) +{ + int answer=0; + while (val>>=1) + answer++; + return answer; +} + + +/* +================ +R_ConcatRotations +================ +*/ +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; +} + + +/* +================ +R_ConcatTransforms +================ +*/ +void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + + in1[2][2] * in2[2][3] + in1[2][3]; +} + + +/* +=================== +FloorDivMod + +Returns mathematically correct (floor-based) quotient and remainder for +numer and denom, both of which should contain no fractional part. The +quotient must fit in 32 bits. +==================== +*/ + +void FloorDivMod (double numer, double denom, int *quotient, + int *rem) +{ + int q, r; + double x; + +#ifndef PARANOID + if (denom <= 0.0) + Sys_Error ("FloorDivMod: bad denominator %d\n", denom); + +// if ((floor(numer) != numer) || (floor(denom) != denom)) +// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n", +// numer, denom); +#endif + + if (numer >= 0.0) + { + + x = floor(numer / denom); + q = (int)x; + r = (int)floor(numer - (x * denom)); + } + else + { + // + // perform operations with positive values, and fix mod to make floor-based + // + x = floor(-numer / denom); + q = -(int)x; + r = (int)floor(-numer - (x * denom)); + if (r != 0) + { + q--; + r = (int)denom - r; + } + } + + *quotient = q; + *rem = r; +} + + +/* +=================== +GreatestCommonDivisor +==================== +*/ +int GreatestCommonDivisor (int i1, int i2) +{ + if (i1 > i2) + { + if (i2 == 0) + return (i1); + return GreatestCommonDivisor (i2, i1 % i2); + } + else + { + if (i1 == 0) + return (i2); + return GreatestCommonDivisor (i1, i2 % i1); + } +} + + +#if !id386 + +// TODO: move to nonintel.c + +/* +=================== +Invert24To16 + +Inverts an 8.24 value to a 16.16 value +==================== +*/ + +fixed16_t Invert24To16(fixed16_t val) +{ + if (val < 256) + return (0xFFFFFFFF); + + return (fixed16_t) + (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5); +} + +#endif diff --git a/WinQuake/mathlib.h b/WinQuake/mathlib.h index b5506e2..ed0cbe8 100644 --- a/WinQuake/mathlib.h +++ b/WinQuake/mathlib.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // mathlib.h typedef float vec_t; diff --git a/WinQuake/menu.c b/WinQuake/menu.c index c3c7ebd..b50b98a 100644 --- a/WinQuake/menu.c +++ b/WinQuake/menu.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #include "quakedef.h" #ifdef _WIN32 @@ -1050,14 +1050,14 @@ void M_Menu_Options_f (void) { key_dest = key_menu; m_state = m_options; - m_entersound = true; + m_entersound = true; -#ifdef _WIN32 - if ((options_cursor == 13) && (modestate != MS_WINDOWED)) - { - options_cursor = 0; - } -#endif +#ifdef _WIN32 + if ((options_cursor == 13) && (modestate != MS_WINDOWED)) + { + options_cursor = 0; + } +#endif } @@ -1687,7 +1687,7 @@ void M_Quit_Draw (void) M_PrintWhite (16, 28, "Programming Art \n"); M_Print (16, 36, " John Carmack Adrian Carmack\n"); M_Print (16, 44, " Michael Abrash Kevin Cloud\n"); - M_Print (16, 52, " John Cash Paul Steed\n"); + M_Print (16, 52, " John Cash Paul Steed\n"); M_Print (16, 60, " Dave 'Zoid' Kirsch\n"); M_PrintWhite (16, 68, "Design Biz\n"); M_Print (16, 76, " John Romero Jay Wilbur\n"); @@ -1695,7 +1695,7 @@ void M_Quit_Draw (void) M_Print (16, 92, " American McGee Donna Jackson\n"); M_Print (16, 100, " Tim Willits Todd Hollenshead\n"); M_PrintWhite (16, 108, "Support Projects\n"); - M_Print (16, 116, " Barrett Alexander Shawn Green\n"); + M_Print (16, 116, " Barrett Alexander Shawn Green\n"); M_PrintWhite (16, 124, "Sound Effects\n"); M_Print (16, 132, " Trent Reznor and Nine Inch Nails\n\n"); M_PrintWhite (16, 140, "Quake is a trademark of Id Software,\n"); diff --git a/WinQuake/menu.h b/WinQuake/menu.h index 616de3f..525218a 100644 --- a/WinQuake/menu.h +++ b/WinQuake/menu.h @@ -1,38 +1,38 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// -// the net drivers should just set the apropriate bits in m_activenet, -// instead of having the menu code look through their internal tables -// -#define MNET_IPX 1 -#define MNET_TCP 2 - -extern int m_activenet; - -// -// menus -// -void M_Init (void); -void M_Keydown (int key); -void M_Draw (void); -void M_ToggleMenu_f (void); - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// the net drivers should just set the apropriate bits in m_activenet, +// instead of having the menu code look through their internal tables +// +#define MNET_IPX 1 +#define MNET_TCP 2 + +extern int m_activenet; + +// +// menus +// +void M_Init (void); +void M_Keydown (int key); +void M_Draw (void); +void M_ToggleMenu_f (void); + + diff --git a/WinQuake/model.c b/WinQuake/model.c index e3bd9fb..c708c86 100644 --- a/WinQuake/model.c +++ b/WinQuake/model.c @@ -1,1874 +1,1874 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// models.c -- model loading and caching - -// models are the only shared resource between a client and server running -// on the same machine. - -#include "quakedef.h" -#include "r_local.h" - -model_t *loadmodel; -char loadname[32]; // for hunk tags - -void Mod_LoadSpriteModel (model_t *mod, void *buffer); -void Mod_LoadBrushModel (model_t *mod, void *buffer); -void Mod_LoadAliasModel (model_t *mod, void *buffer); -model_t *Mod_LoadModel (model_t *mod, qboolean crash); - -byte mod_novis[MAX_MAP_LEAFS/8]; - -#define MAX_MOD_KNOWN 256 -model_t mod_known[MAX_MOD_KNOWN]; -int mod_numknown; - -// values for model_t's needload -#define NL_PRESENT 0 -#define NL_NEEDS_LOADED 1 -#define NL_UNREFERENCED 2 - -/* -=============== -Mod_Init -=============== -*/ -void Mod_Init (void) -{ - memset (mod_novis, 0xff, sizeof(mod_novis)); -} - -/* -=============== -Mod_Extradata - -Caches the data if needed -=============== -*/ -void *Mod_Extradata (model_t *mod) -{ - void *r; - - r = Cache_Check (&mod->cache); - if (r) - return r; - - Mod_LoadModel (mod, true); - - if (!mod->cache.data) - Sys_Error ("Mod_Extradata: caching failed"); - return mod->cache.data; -} - -/* -=============== -Mod_PointInLeaf -=============== -*/ -mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) -{ - mnode_t *node; - float d; - mplane_t *plane; - - if (!model || !model->nodes) - Sys_Error ("Mod_PointInLeaf: bad model"); - - node = model->nodes; - while (1) - { - if (node->contents < 0) - return (mleaf_t *)node; - plane = node->plane; - d = DotProduct (p,plane->normal) - plane->dist; - if (d > 0) - node = node->children[0]; - else - node = node->children[1]; - } - - return NULL; // never reached -} - - -/* -=================== -Mod_DecompressVis -=================== -*/ -byte *Mod_DecompressVis (byte *in, model_t *model) -{ - static byte decompressed[MAX_MAP_LEAFS/8]; - int c; - byte *out; - int row; - - row = (model->numleafs+7)>>3; - out = decompressed; - - if (!in) - { // no vis info, so make all visible - while (row) - { - *out++ = 0xff; - row--; - } - return decompressed; - } - - do - { - if (*in) - { - *out++ = *in++; - continue; - } - - c = in[1]; - in += 2; - while (c) - { - *out++ = 0; - c--; - } - } while (out - decompressed < row); - - return decompressed; -} - -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) -{ - if (leaf == model->leafs) - return mod_novis; - return Mod_DecompressVis (leaf->compressed_vis, model); -} - -/* -=================== -Mod_ClearAll -=================== -*/ -void Mod_ClearAll (void) -{ - int i; - model_t *mod; - - - for (i=0 , mod=mod_known ; ineedload = NL_UNREFERENCED; -//FIX FOR CACHE_ALLOC ERRORS: - if (mod->type == mod_sprite) mod->cache.data = NULL; - } -} - -/* -================== -Mod_FindName - -================== -*/ -model_t *Mod_FindName (char *name) -{ - int i; - model_t *mod; - model_t *avail = NULL; - - if (!name[0]) - Sys_Error ("Mod_ForName: NULL name"); - -// -// search the currently loaded models -// - for (i=0 , mod=mod_known ; iname, name) ) - break; - if (mod->needload == NL_UNREFERENCED) - if (!avail || mod->type != mod_alias) - avail = mod; - } - - if (i == mod_numknown) - { - if (mod_numknown == MAX_MOD_KNOWN) - { - if (avail) - { - mod = avail; - if (mod->type == mod_alias) - if (Cache_Check (&mod->cache)) - Cache_Free (&mod->cache); - } - else - Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); - } - else - mod_numknown++; - strcpy (mod->name, name); - mod->needload = NL_NEEDS_LOADED; - } - - return mod; -} - -/* -================== -Mod_TouchModel - -================== -*/ -void Mod_TouchModel (char *name) -{ - model_t *mod; - - mod = Mod_FindName (name); - - if (mod->needload == NL_PRESENT) - { - if (mod->type == mod_alias) - Cache_Check (&mod->cache); - } -} - -/* -================== -Mod_LoadModel - -Loads a model into the cache -================== -*/ -model_t *Mod_LoadModel (model_t *mod, qboolean crash) -{ - unsigned *buf; - byte stackbuf[1024]; // avoid dirtying the cache heap - - if (mod->type == mod_alias) - { - if (Cache_Check (&mod->cache)) - { - mod->needload = NL_PRESENT; - return mod; - } - } - else - { - if (mod->needload == NL_PRESENT) - return mod; - } - -// -// because the world is so huge, load it one piece at a time -// - -// -// load the file -// - buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); - if (!buf) - { - if (crash) - Sys_Error ("Mod_NumForName: %s not found", mod->name); - return NULL; - } - -// -// allocate a new model -// - COM_FileBase (mod->name, loadname); - - loadmodel = mod; - -// -// fill it in -// - -// call the apropriate loader - mod->needload = NL_PRESENT; - - switch (LittleLong(*(unsigned *)buf)) - { - case IDPOLYHEADER: - Mod_LoadAliasModel (mod, buf); - break; - - case IDSPRITEHEADER: - Mod_LoadSpriteModel (mod, buf); - break; - - default: - Mod_LoadBrushModel (mod, buf); - break; - } - - return mod; -} - -/* -================== -Mod_ForName - -Loads in a model for the given name -================== -*/ -model_t *Mod_ForName (char *name, qboolean crash) -{ - model_t *mod; - - mod = Mod_FindName (name); - - return Mod_LoadModel (mod, crash); -} - - -/* -=============================================================================== - - BRUSHMODEL LOADING - -=============================================================================== -*/ - -byte *mod_base; - - -/* -================= -Mod_LoadTextures -================= -*/ -void Mod_LoadTextures (lump_t *l) -{ - int i, j, pixels, num, max, altmax; - miptex_t *mt; - texture_t *tx, *tx2; - texture_t *anims[10]; - texture_t *altanims[10]; - dmiptexlump_t *m; - - if (!l->filelen) - { - loadmodel->textures = NULL; - return; - } - m = (dmiptexlump_t *)(mod_base + l->fileofs); - - m->nummiptex = LittleLong (m->nummiptex); - - loadmodel->numtextures = m->nummiptex; - loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); - - for (i=0 ; inummiptex ; i++) - { - m->dataofs[i] = LittleLong(m->dataofs[i]); - if (m->dataofs[i] == -1) - continue; - mt = (miptex_t *)((byte *)m + m->dataofs[i]); - mt->width = LittleLong (mt->width); - mt->height = LittleLong (mt->height); - for (j=0 ; joffsets[j] = LittleLong (mt->offsets[j]); - - if ( (mt->width & 15) || (mt->height & 15) ) - Sys_Error ("Texture %s is not 16 aligned", mt->name); - pixels = mt->width*mt->height/64*85; - tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); - loadmodel->textures[i] = tx; - - memcpy (tx->name, mt->name, sizeof(tx->name)); - tx->width = mt->width; - tx->height = mt->height; - for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); - // the pixels immediately follow the structures - memcpy ( tx+1, mt+1, pixels); - - if (!Q_strncmp(mt->name,"sky",3)) - R_InitSky (tx); - } - -// -// sequence the animations -// - for (i=0 ; inummiptex ; i++) - { - tx = loadmodel->textures[i]; - if (!tx || tx->name[0] != '+') - continue; - if (tx->anim_next) - continue; // allready sequenced - - // find the number of frames in the animation - memset (anims, 0, sizeof(anims)); - memset (altanims, 0, sizeof(altanims)); - - max = tx->name[1]; - altmax = 0; - if (max >= 'a' && max <= 'z') - max -= 'a' - 'A'; - if (max >= '0' && max <= '9') - { - max -= '0'; - altmax = 0; - anims[max] = tx; - max++; - } - else if (max >= 'A' && max <= 'J') - { - altmax = max - 'A'; - max = 0; - altanims[altmax] = tx; - altmax++; - } - else - Sys_Error ("Bad animating texture %s", tx->name); - - for (j=i+1 ; jnummiptex ; j++) - { - tx2 = loadmodel->textures[j]; - if (!tx2 || tx2->name[0] != '+') - continue; - if (strcmp (tx2->name+2, tx->name+2)) - continue; - - num = tx2->name[1]; - if (num >= 'a' && num <= 'z') - num -= 'a' - 'A'; - if (num >= '0' && num <= '9') - { - num -= '0'; - anims[num] = tx2; - if (num+1 > max) - max = num + 1; - } - else if (num >= 'A' && num <= 'J') - { - num = num - 'A'; - altanims[num] = tx2; - if (num+1 > altmax) - altmax = num+1; - } - else - Sys_Error ("Bad animating texture %s", tx->name); - } - -#define ANIM_CYCLE 2 - // link them all together - for (j=0 ; jname); - tx2->anim_total = max * ANIM_CYCLE; - tx2->anim_min = j * ANIM_CYCLE; - tx2->anim_max = (j+1) * ANIM_CYCLE; - tx2->anim_next = anims[ (j+1)%max ]; - if (altmax) - tx2->alternate_anims = altanims[0]; - } - for (j=0 ; jname); - tx2->anim_total = altmax * ANIM_CYCLE; - tx2->anim_min = j * ANIM_CYCLE; - tx2->anim_max = (j+1) * ANIM_CYCLE; - tx2->anim_next = altanims[ (j+1)%altmax ]; - if (max) - tx2->alternate_anims = anims[0]; - } - } -} - -/* -================= -Mod_LoadLighting -================= -*/ -void Mod_LoadLighting (lump_t *l) -{ - if (!l->filelen) - { - loadmodel->lightdata = NULL; - return; - } - loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); - memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); -} - - -/* -================= -Mod_LoadVisibility -================= -*/ -void Mod_LoadVisibility (lump_t *l) -{ - if (!l->filelen) - { - loadmodel->visdata = NULL; - return; - } - loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); - memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); -} - - -/* -================= -Mod_LoadEntities -================= -*/ -void Mod_LoadEntities (lump_t *l) -{ - if (!l->filelen) - { - loadmodel->entities = NULL; - return; - } - loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); - memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); -} - - -/* -================= -Mod_LoadVertexes -================= -*/ -void Mod_LoadVertexes (lump_t *l) -{ - dvertex_t *in; - mvertex_t *out; - int i, count; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->vertexes = out; - loadmodel->numvertexes = count; - - for ( i=0 ; iposition[0] = LittleFloat (in->point[0]); - out->position[1] = LittleFloat (in->point[1]); - out->position[2] = LittleFloat (in->point[2]); - } -} - -/* -================= -Mod_LoadSubmodels -================= -*/ -void Mod_LoadSubmodels (lump_t *l) -{ - dmodel_t *in; - dmodel_t *out; - int i, j, count; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->submodels = out; - loadmodel->numsubmodels = count; - - for ( i=0 ; imins[j] = LittleFloat (in->mins[j]) - 1; - out->maxs[j] = LittleFloat (in->maxs[j]) + 1; - out->origin[j] = LittleFloat (in->origin[j]); - } - for (j=0 ; jheadnode[j] = LittleLong (in->headnode[j]); - out->visleafs = LittleLong (in->visleafs); - out->firstface = LittleLong (in->firstface); - out->numfaces = LittleLong (in->numfaces); - } -} - -/* -================= -Mod_LoadEdges -================= -*/ -void Mod_LoadEdges (lump_t *l) -{ - dedge_t *in; - medge_t *out; - int i, count; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); - - loadmodel->edges = out; - loadmodel->numedges = count; - - for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); - out->v[1] = (unsigned short)LittleShort(in->v[1]); - } -} - -/* -================= -Mod_LoadTexinfo -================= -*/ -void Mod_LoadTexinfo (lump_t *l) -{ - texinfo_t *in; - mtexinfo_t *out; - int i, j, count; - int miptex; - float len1, len2; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->texinfo = out; - loadmodel->numtexinfo = count; - - for ( i=0 ; ivecs[0][j] = LittleFloat (in->vecs[0][j]); - len1 = Length (out->vecs[0]); - len2 = Length (out->vecs[1]); - len1 = (len1 + len2)/2; - if (len1 < 0.32) - out->mipadjust = 4; - else if (len1 < 0.49) - out->mipadjust = 3; - else if (len1 < 0.99) - out->mipadjust = 2; - else - out->mipadjust = 1; -#if 0 - if (len1 + len2 < 0.001) - out->mipadjust = 1; // don't crash - else - out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); -#endif - - miptex = LittleLong (in->miptex); - out->flags = LittleLong (in->flags); - - if (!loadmodel->textures) - { - out->texture = r_notexture_mip; // checkerboard texture - out->flags = 0; - } - else - { - if (miptex >= loadmodel->numtextures) - Sys_Error ("miptex >= loadmodel->numtextures"); - out->texture = loadmodel->textures[miptex]; - if (!out->texture) - { - out->texture = r_notexture_mip; // texture not found - out->flags = 0; - } - } - } -} - -/* -================ -CalcSurfaceExtents - -Fills in s->texturemins[] and s->extents[] -================ -*/ -void CalcSurfaceExtents (msurface_t *s) -{ - float mins[2], maxs[2], val; - int i,j, e; - mvertex_t *v; - mtexinfo_t *tex; - int bmins[2], bmaxs[2]; - - mins[0] = mins[1] = 999999; - maxs[0] = maxs[1] = -99999; - - tex = s->texinfo; - - for (i=0 ; inumedges ; i++) - { - e = loadmodel->surfedges[s->firstedge+i]; - if (e >= 0) - v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; - else - v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; - - for (j=0 ; j<2 ; j++) - { - val = v->position[0] * tex->vecs[j][0] + - v->position[1] * tex->vecs[j][1] + - v->position[2] * tex->vecs[j][2] + - tex->vecs[j][3]; - if (val < mins[j]) - mins[j] = val; - if (val > maxs[j]) - maxs[j] = val; - } - } - - for (i=0 ; i<2 ; i++) - { - bmins[i] = floor(mins[i]/16); - bmaxs[i] = ceil(maxs[i]/16); - - s->texturemins[i] = bmins[i] * 16; - s->extents[i] = (bmaxs[i] - bmins[i]) * 16; - if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256) - Sys_Error ("Bad surface extents"); - } -} - - -/* -================= -Mod_LoadFaces -================= -*/ -void Mod_LoadFaces (lump_t *l) -{ - dface_t *in; - msurface_t *out; - int i, count, surfnum; - int planenum, side; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->surfaces = out; - loadmodel->numsurfaces = count; - - for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); - out->flags = 0; - - planenum = LittleShort(in->planenum); - side = LittleShort(in->side); - if (side) - out->flags |= SURF_PLANEBACK; - - out->plane = loadmodel->planes + planenum; - - out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); - - CalcSurfaceExtents (out); - - // lighting info - - for (i=0 ; istyles[i] = in->styles[i]; - i = LittleLong(in->lightofs); - if (i == -1) - out->samples = NULL; - else - out->samples = loadmodel->lightdata + i; - - // set the drawing flags flag - - if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky - { - out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); - continue; - } - - if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent - { - out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); - for (i=0 ; i<2 ; i++) - { - out->extents[i] = 16384; - out->texturemins[i] = -8192; - } - continue; - } - } -} - - -/* -================= -Mod_SetParent -================= -*/ -void Mod_SetParent (mnode_t *node, mnode_t *parent) -{ - node->parent = parent; - if (node->contents < 0) - return; - Mod_SetParent (node->children[0], node); - Mod_SetParent (node->children[1], node); -} - -/* -================= -Mod_LoadNodes -================= -*/ -void Mod_LoadNodes (lump_t *l) -{ - int i, j, count, p; - dnode_t *in; - mnode_t *out; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->nodes = out; - loadmodel->numnodes = count; - - for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); - } - - p = LittleLong(in->planenum); - out->plane = loadmodel->planes + p; - - out->firstsurface = LittleShort (in->firstface); - out->numsurfaces = LittleShort (in->numfaces); - - for (j=0 ; j<2 ; j++) - { - p = LittleShort (in->children[j]); - if (p >= 0) - out->children[j] = loadmodel->nodes + p; - else - out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); - } - } - - Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs -} - -/* -================= -Mod_LoadLeafs -================= -*/ -void Mod_LoadLeafs (lump_t *l) -{ - dleaf_t *in; - mleaf_t *out; - int i, j, count, p; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->leafs = out; - loadmodel->numleafs = count; - - for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); - } - - p = LittleLong(in->contents); - out->contents = p; - - out->firstmarksurface = loadmodel->marksurfaces + - LittleShort(in->firstmarksurface); - out->nummarksurfaces = LittleShort(in->nummarksurfaces); - - p = LittleLong(in->visofs); - if (p == -1) - out->compressed_vis = NULL; - else - out->compressed_vis = loadmodel->visdata + p; - out->efrags = NULL; - - for (j=0 ; j<4 ; j++) - out->ambient_sound_level[j] = in->ambient_level[j]; - } -} - -/* -================= -Mod_LoadClipnodes -================= -*/ -void Mod_LoadClipnodes (lump_t *l) -{ - dclipnode_t *in, *out; - int i, count; - hull_t *hull; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->clipnodes = out; - loadmodel->numclipnodes = count; - - hull = &loadmodel->hulls[1]; - hull->clipnodes = out; - hull->firstclipnode = 0; - hull->lastclipnode = count-1; - hull->planes = loadmodel->planes; - hull->clip_mins[0] = -16; - hull->clip_mins[1] = -16; - hull->clip_mins[2] = -24; - hull->clip_maxs[0] = 16; - hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 32; - - hull = &loadmodel->hulls[2]; - hull->clipnodes = out; - hull->firstclipnode = 0; - hull->lastclipnode = count-1; - hull->planes = loadmodel->planes; - hull->clip_mins[0] = -32; - hull->clip_mins[1] = -32; - hull->clip_mins[2] = -24; - hull->clip_maxs[0] = 32; - hull->clip_maxs[1] = 32; - hull->clip_maxs[2] = 64; - - for (i=0 ; iplanenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); - out->children[1] = LittleShort(in->children[1]); - } -} - -/* -================= -Mod_MakeHull0 - -Deplicate the drawing hull structure as a clipping hull -================= -*/ -void Mod_MakeHull0 (void) -{ - mnode_t *in, *child; - dclipnode_t *out; - int i, j, count; - hull_t *hull; - - hull = &loadmodel->hulls[0]; - - in = loadmodel->nodes; - count = loadmodel->numnodes; - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - hull->clipnodes = out; - hull->firstclipnode = 0; - hull->lastclipnode = count-1; - hull->planes = loadmodel->planes; - - for (i=0 ; iplanenum = in->plane - loadmodel->planes; - for (j=0 ; j<2 ; j++) - { - child = in->children[j]; - if (child->contents < 0) - out->children[j] = child->contents; - else - out->children[j] = child - loadmodel->nodes; - } - } -} - -/* -================= -Mod_LoadMarksurfaces -================= -*/ -void Mod_LoadMarksurfaces (lump_t *l) -{ - int i, j, count; - short *in; - msurface_t **out; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->marksurfaces = out; - loadmodel->nummarksurfaces = count; - - for ( i=0 ; i= loadmodel->numsurfaces) - Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); - out[i] = loadmodel->surfaces + j; - } -} - -/* -================= -Mod_LoadSurfedges -================= -*/ -void Mod_LoadSurfedges (lump_t *l) -{ - int i, count; - int *in, *out; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->surfedges = out; - loadmodel->numsurfedges = count; - - for ( i=0 ; ifileofs); - if (l->filelen % sizeof(*in)) - Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*2*sizeof(*out), loadname); - - loadmodel->planes = out; - loadmodel->numplanes = count; - - for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); - if (out->normal[j] < 0) - bits |= 1<dist = LittleFloat (in->dist); - out->type = LittleLong (in->type); - out->signbits = bits; - } -} - -/* -================= -RadiusFromBounds -================= -*/ -float RadiusFromBounds (vec3_t mins, vec3_t maxs) -{ - int i; - vec3_t corner; - - for (i=0 ; i<3 ; i++) - { - corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); - } - - return Length (corner); -} - -/* -================= -Mod_LoadBrushModel -================= -*/ -void Mod_LoadBrushModel (model_t *mod, void *buffer) -{ - int i, j; - dheader_t *header; - dmodel_t *bm; - - loadmodel->type = mod_brush; - - header = (dheader_t *)buffer; - - i = LittleLong (header->version); - if (i != BSPVERSION) - Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); - -// swap all the lumps - mod_base = (byte *)header; - - for (i=0 ; ilumps[LUMP_VERTEXES]); - Mod_LoadEdges (&header->lumps[LUMP_EDGES]); - Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); - Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); - Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); - Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); - Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); - Mod_LoadFaces (&header->lumps[LUMP_FACES]); - Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); - Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); - Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); - Mod_LoadNodes (&header->lumps[LUMP_NODES]); - Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); - Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); - Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); - - Mod_MakeHull0 (); - - mod->numframes = 2; // regular and alternate animation - mod->flags = 0; - -// -// set up the submodels (FIXME: this is confusing) -// - for (i=0 ; inumsubmodels ; i++) - { - bm = &mod->submodels[i]; - - mod->hulls[0].firstclipnode = bm->headnode[0]; - for (j=1 ; jhulls[j].firstclipnode = bm->headnode[j]; - mod->hulls[j].lastclipnode = mod->numclipnodes-1; - } - - mod->firstmodelsurface = bm->firstface; - mod->nummodelsurfaces = bm->numfaces; - - VectorCopy (bm->maxs, mod->maxs); - VectorCopy (bm->mins, mod->mins); - mod->radius = RadiusFromBounds (mod->mins, mod->maxs); - - mod->numleafs = bm->visleafs; - - if (i < mod->numsubmodels-1) - { // duplicate the basic information - char name[10]; - - sprintf (name, "*%i", i+1); - loadmodel = Mod_FindName (name); - *loadmodel = *mod; - strcpy (loadmodel->name, name); - mod = loadmodel; - } - } -} - -/* -============================================================================== - -ALIAS MODELS - -============================================================================== -*/ - -/* -================= -Mod_LoadAliasFrame -================= -*/ -void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv, - trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name) -{ - trivertx_t *pframe, *pinframe; - int i, j; - daliasframe_t *pdaliasframe; - - pdaliasframe = (daliasframe_t *)pin; - - strcpy (name, pdaliasframe->name); - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about - // endianness - pbboxmin->v[i] = pdaliasframe->bboxmin.v[i]; - pbboxmax->v[i] = pdaliasframe->bboxmax.v[i]; - } - - pinframe = (trivertx_t *)(pdaliasframe + 1); - pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname); - - *pframeindex = (byte *)pframe - (byte *)pheader; - - for (j=0 ; jnumframes); - - paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) + - (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname); - - paliasgroup->numframes = numframes; - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about endianness - pbboxmin->v[i] = pingroup->bboxmin.v[i]; - pbboxmax->v[i] = pingroup->bboxmax.v[i]; - } - - *pframeindex = (byte *)paliasgroup - (byte *)pheader; - - pin_intervals = (daliasinterval_t *)(pingroup + 1); - - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); - - paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader; - - for (i=0 ; iinterval); - if (*poutintervals <= 0.0) - Sys_Error ("Mod_LoadAliasGroup: interval<=0"); - - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - - for (i=0 ; iframes[i].frame, - numv, - &paliasgroup->frames[i].bboxmin, - &paliasgroup->frames[i].bboxmax, - pheader, name); - } - - return ptemp; -} - - -/* -================= -Mod_LoadAliasSkin -================= -*/ -void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize, - aliashdr_t *pheader) -{ - int i; - byte *pskin, *pinskin; - unsigned short *pusskin; - - pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); - pinskin = (byte *)pin; - *pskinindex = (byte *)pskin - (byte *)pheader; - - if (r_pixbytes == 1) - { - Q_memcpy (pskin, pinskin, skinsize); - } - else if (r_pixbytes == 2) - { - pusskin = (unsigned short *)pskin; - - for (i=0 ; inumskins); - - paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) + - (numskins - 1) * sizeof (paliasskingroup->skindescs[0]), - loadname); - - paliasskingroup->numskins = numskins; - - *pskinindex = (byte *)paliasskingroup - (byte *)pheader; - - pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); - - poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname); - - paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader; - - for (i=0 ; iinterval); - if (*poutskinintervals <= 0) - Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); - - poutskinintervals++; - pinskinintervals++; - } - - ptemp = (void *)pinskinintervals; - - for (i=0 ; iskindescs[i].skin, skinsize, pheader); - } - - return ptemp; -} - - -/* -================= -Mod_LoadAliasModel -================= -*/ -void Mod_LoadAliasModel (model_t *mod, void *buffer) -{ - int i; - mdl_t *pmodel, *pinmodel; - stvert_t *pstverts, *pinstverts; - aliashdr_t *pheader; - mtriangle_t *ptri; - dtriangle_t *pintriangles; - int version, numframes, numskins; - int size; - daliasframetype_t *pframetype; - daliasskintype_t *pskintype; - maliasskindesc_t *pskindesc; - int skinsize; - int start, end, total; - - start = Hunk_LowMark (); - - pinmodel = (mdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - Sys_Error ("%s has wrong version number (%i should be %i)", - mod->name, version, ALIAS_VERSION); - -// -// allocate space for a working header, plus all the data except the frames, -// skin and group info -// - size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * - sizeof (pheader->frames[0]) + - sizeof (mdl_t) + - LittleLong (pinmodel->numverts) * sizeof (stvert_t) + - LittleLong (pinmodel->numtris) * sizeof (mtriangle_t); - - pheader = Hunk_AllocName (size, loadname); - pmodel = (mdl_t *) ((byte *)&pheader[1] + - (LittleLong (pinmodel->numframes) - 1) * - sizeof (pheader->frames[0])); - -// mod->cache.data = pheader; - mod->flags = LittleLong (pinmodel->flags); - -// -// endian-adjust and copy the data, starting with the alias model header -// - pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); - pmodel->numskins = LittleLong (pinmodel->numskins); - pmodel->skinwidth = LittleLong (pinmodel->skinwidth); - pmodel->skinheight = LittleLong (pinmodel->skinheight); - - if (pmodel->skinheight > MAX_LBM_HEIGHT) - Sys_Error ("model %s has a skin taller than %d", mod->name, - MAX_LBM_HEIGHT); - - pmodel->numverts = LittleLong (pinmodel->numverts); - - if (pmodel->numverts <= 0) - Sys_Error ("model %s has no vertices", mod->name); - - if (pmodel->numverts > MAXALIASVERTS) - Sys_Error ("model %s has too many vertices", mod->name); - - pmodel->numtris = LittleLong (pinmodel->numtris); - - if (pmodel->numtris <= 0) - Sys_Error ("model %s has no triangles", mod->name); - - pmodel->numframes = LittleLong (pinmodel->numframes); - pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; - mod->synctype = LittleLong (pinmodel->synctype); - mod->numframes = pmodel->numframes; - - for (i=0 ; i<3 ; i++) - { - pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); - pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); - pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); - } - - numskins = pmodel->numskins; - numframes = pmodel->numframes; - - if (pmodel->skinwidth & 0x03) - Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4"); - - pheader->model = (byte *)pmodel - (byte *)pheader; - -// -// load the skins -// - skinsize = pmodel->skinheight * pmodel->skinwidth; - - if (numskins < 1) - Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); - - pskintype = (daliasskintype_t *)&pinmodel[1]; - - pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), - loadname); - - pheader->skindesc = (byte *)pskindesc - (byte *)pheader; - - for (i=0 ; itype); - pskindesc[i].type = skintype; - - if (skintype == ALIAS_SKIN_SINGLE) - { - pskintype = (daliasskintype_t *) - Mod_LoadAliasSkin (pskintype + 1, - &pskindesc[i].skin, - skinsize, pheader); - } - else - { - pskintype = (daliasskintype_t *) - Mod_LoadAliasSkinGroup (pskintype + 1, - &pskindesc[i].skin, - skinsize, pheader); - } - } - -// -// set base s and t vertices -// - pstverts = (stvert_t *)&pmodel[1]; - pinstverts = (stvert_t *)pskintype; - - pheader->stverts = (byte *)pstverts - (byte *)pheader; - - for (i=0 ; inumverts ; i++) - { - pstverts[i].onseam = LittleLong (pinstverts[i].onseam); - // put s and t in 16.16 format - pstverts[i].s = LittleLong (pinstverts[i].s) << 16; - pstverts[i].t = LittleLong (pinstverts[i].t) << 16; - } - -// -// set up the triangles -// - ptri = (mtriangle_t *)&pstverts[pmodel->numverts]; - pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts]; - - pheader->triangles = (byte *)ptri - (byte *)pheader; - - for (i=0 ; inumtris ; i++) - { - int j; - - ptri[i].facesfront = LittleLong (pintriangles[i].facesfront); - - for (j=0 ; j<3 ; j++) - { - ptri[i].vertindex[j] = - LittleLong (pintriangles[i].vertindex[j]); - } - } - -// -// load the frames -// - if (numframes < 1) - Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); - - pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; - - for (i=0 ; itype); - pheader->frames[i].type = frametype; - - if (frametype == ALIAS_SINGLE) - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasFrame (pframetype + 1, - &pheader->frames[i].frame, - pmodel->numverts, - &pheader->frames[i].bboxmin, - &pheader->frames[i].bboxmax, - pheader, pheader->frames[i].name); - } - else - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasGroup (pframetype + 1, - &pheader->frames[i].frame, - pmodel->numverts, - &pheader->frames[i].bboxmin, - &pheader->frames[i].bboxmax, - pheader, pheader->frames[i].name); - } - } - - mod->type = mod_alias; - -// FIXME: do this right - mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; - mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; - -// -// move the complete, relocatable alias model to the cache -// - end = Hunk_LowMark (); - total = end - start; - - Cache_Alloc (&mod->cache, total, loadname); - if (!mod->cache.data) - return; - memcpy (mod->cache.data, pheader, total); - - Hunk_FreeToLowMark (start); -} - -//============================================================================= - -/* -================= -Mod_LoadSpriteFrame -================= -*/ -void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe) -{ - dspriteframe_t *pinframe; - mspriteframe_t *pspriteframe; - int i, width, height, size, origin[2]; - unsigned short *ppixout; - byte *ppixin; - - pinframe = (dspriteframe_t *)pin; - - width = LittleLong (pinframe->width); - height = LittleLong (pinframe->height); - size = width * height; - - pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes, - loadname); - - Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); - *ppframe = pspriteframe; - - pspriteframe->width = width; - pspriteframe->height = height; - origin[0] = LittleLong (pinframe->origin[0]); - origin[1] = LittleLong (pinframe->origin[1]); - - pspriteframe->up = origin[1]; - pspriteframe->down = origin[1] - height; - pspriteframe->left = origin[0]; - pspriteframe->right = width + origin[0]; - - if (r_pixbytes == 1) - { - Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size); - } - else if (r_pixbytes == 2) - { - ppixin = (byte *)(pinframe + 1); - ppixout = (unsigned short *)&pspriteframe->pixels[0]; - - for (i=0 ; inumframes); - - pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + - (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); - - pspritegroup->numframes = numframes; - - *ppframe = (mspriteframe_t *)pspritegroup; - - pin_intervals = (dspriteinterval_t *)(pingroup + 1); - - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); - - pspritegroup->intervals = poutintervals; - - for (i=0 ; iinterval); - if (*poutintervals <= 0.0) - Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); - - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - - for (i=0 ; iframes[i]); - } - - return ptemp; -} - - -/* -================= -Mod_LoadSpriteModel -================= -*/ -void Mod_LoadSpriteModel (model_t *mod, void *buffer) -{ - int i; - int version; - dsprite_t *pin; - msprite_t *psprite; - int numframes; - int size; - dspriteframetype_t *pframetype; - - pin = (dsprite_t *)buffer; - - version = LittleLong (pin->version); - if (version != SPRITE_VERSION) - Sys_Error ("%s has wrong version number " - "(%i should be %i)", mod->name, version, SPRITE_VERSION); - - numframes = LittleLong (pin->numframes); - - size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); - - psprite = Hunk_AllocName (size, loadname); - - mod->cache.data = psprite; - - psprite->type = LittleLong (pin->type); - psprite->maxwidth = LittleLong (pin->width); - psprite->maxheight = LittleLong (pin->height); - psprite->beamlength = LittleFloat (pin->beamlength); - mod->synctype = LittleLong (pin->synctype); - psprite->numframes = numframes; - - mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; - mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; - mod->mins[2] = -psprite->maxheight/2; - mod->maxs[2] = psprite->maxheight/2; - -// -// load the frames -// - if (numframes < 1) - Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); - - mod->numframes = numframes; - mod->flags = 0; - - pframetype = (dspriteframetype_t *)(pin + 1); - - for (i=0 ; itype); - psprite->frames[i].type = frametype; - - if (frametype == SPR_SINGLE) - { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteFrame (pframetype + 1, - &psprite->frames[i].frameptr); - } - else - { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteGroup (pframetype + 1, - &psprite->frames[i].frameptr); - } - } - - mod->type = mod_sprite; -} - -//============================================================================= - -/* -================ -Mod_Print -================ -*/ -void Mod_Print (void) -{ - int i; - model_t *mod; - - Con_Printf ("Cached models:\n"); - for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) - { - Con_Printf ("%8p : %s",mod->cache.data, mod->name); - if (mod->needload & NL_UNREFERENCED) - Con_Printf (" (!R)"); - if (mod->needload & NL_NEEDS_LOADED) - Con_Printf (" (!P)"); - Con_Printf ("\n"); - } -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// models.c -- model loading and caching + +// models are the only shared resource between a client and server running +// on the same machine. + +#include "quakedef.h" +#include "r_local.h" + +model_t *loadmodel; +char loadname[32]; // for hunk tags + +void Mod_LoadSpriteModel (model_t *mod, void *buffer); +void Mod_LoadBrushModel (model_t *mod, void *buffer); +void Mod_LoadAliasModel (model_t *mod, void *buffer); +model_t *Mod_LoadModel (model_t *mod, qboolean crash); + +byte mod_novis[MAX_MAP_LEAFS/8]; + +#define MAX_MOD_KNOWN 256 +model_t mod_known[MAX_MOD_KNOWN]; +int mod_numknown; + +// values for model_t's needload +#define NL_PRESENT 0 +#define NL_NEEDS_LOADED 1 +#define NL_UNREFERENCED 2 + +/* +=============== +Mod_Init +=============== +*/ +void Mod_Init (void) +{ + memset (mod_novis, 0xff, sizeof(mod_novis)); +} + +/* +=============== +Mod_Extradata + +Caches the data if needed +=============== +*/ +void *Mod_Extradata (model_t *mod) +{ + void *r; + + r = Cache_Check (&mod->cache); + if (r) + return r; + + Mod_LoadModel (mod, true); + + if (!mod->cache.data) + Sys_Error ("Mod_Extradata: caching failed"); + return mod->cache.data; +} + +/* +=============== +Mod_PointInLeaf +=============== +*/ +mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) +{ + mnode_t *node; + float d; + mplane_t *plane; + + if (!model || !model->nodes) + Sys_Error ("Mod_PointInLeaf: bad model"); + + node = model->nodes; + while (1) + { + if (node->contents < 0) + return (mleaf_t *)node; + plane = node->plane; + d = DotProduct (p,plane->normal) - plane->dist; + if (d > 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return NULL; // never reached +} + + +/* +=================== +Mod_DecompressVis +=================== +*/ +byte *Mod_DecompressVis (byte *in, model_t *model) +{ + static byte decompressed[MAX_MAP_LEAFS/8]; + int c; + byte *out; + int row; + + row = (model->numleafs+7)>>3; + out = decompressed; + + if (!in) + { // no vis info, so make all visible + while (row) + { + *out++ = 0xff; + row--; + } + return decompressed; + } + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); + + return decompressed; +} + +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) +{ + if (leaf == model->leafs) + return mod_novis; + return Mod_DecompressVis (leaf->compressed_vis, model); +} + +/* +=================== +Mod_ClearAll +=================== +*/ +void Mod_ClearAll (void) +{ + int i; + model_t *mod; + + + for (i=0 , mod=mod_known ; ineedload = NL_UNREFERENCED; +//FIX FOR CACHE_ALLOC ERRORS: + if (mod->type == mod_sprite) mod->cache.data = NULL; + } +} + +/* +================== +Mod_FindName + +================== +*/ +model_t *Mod_FindName (char *name) +{ + int i; + model_t *mod; + model_t *avail = NULL; + + if (!name[0]) + Sys_Error ("Mod_ForName: NULL name"); + +// +// search the currently loaded models +// + for (i=0 , mod=mod_known ; iname, name) ) + break; + if (mod->needload == NL_UNREFERENCED) + if (!avail || mod->type != mod_alias) + avail = mod; + } + + if (i == mod_numknown) + { + if (mod_numknown == MAX_MOD_KNOWN) + { + if (avail) + { + mod = avail; + if (mod->type == mod_alias) + if (Cache_Check (&mod->cache)) + Cache_Free (&mod->cache); + } + else + Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); + } + else + mod_numknown++; + strcpy (mod->name, name); + mod->needload = NL_NEEDS_LOADED; + } + + return mod; +} + +/* +================== +Mod_TouchModel + +================== +*/ +void Mod_TouchModel (char *name) +{ + model_t *mod; + + mod = Mod_FindName (name); + + if (mod->needload == NL_PRESENT) + { + if (mod->type == mod_alias) + Cache_Check (&mod->cache); + } +} + +/* +================== +Mod_LoadModel + +Loads a model into the cache +================== +*/ +model_t *Mod_LoadModel (model_t *mod, qboolean crash) +{ + unsigned *buf; + byte stackbuf[1024]; // avoid dirtying the cache heap + + if (mod->type == mod_alias) + { + if (Cache_Check (&mod->cache)) + { + mod->needload = NL_PRESENT; + return mod; + } + } + else + { + if (mod->needload == NL_PRESENT) + return mod; + } + +// +// because the world is so huge, load it one piece at a time +// + +// +// load the file +// + buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); + if (!buf) + { + if (crash) + Sys_Error ("Mod_NumForName: %s not found", mod->name); + return NULL; + } + +// +// allocate a new model +// + COM_FileBase (mod->name, loadname); + + loadmodel = mod; + +// +// fill it in +// + +// call the apropriate loader + mod->needload = NL_PRESENT; + + switch (LittleLong(*(unsigned *)buf)) + { + case IDPOLYHEADER: + Mod_LoadAliasModel (mod, buf); + break; + + case IDSPRITEHEADER: + Mod_LoadSpriteModel (mod, buf); + break; + + default: + Mod_LoadBrushModel (mod, buf); + break; + } + + return mod; +} + +/* +================== +Mod_ForName + +Loads in a model for the given name +================== +*/ +model_t *Mod_ForName (char *name, qboolean crash) +{ + model_t *mod; + + mod = Mod_FindName (name); + + return Mod_LoadModel (mod, crash); +} + + +/* +=============================================================================== + + BRUSHMODEL LOADING + +=============================================================================== +*/ + +byte *mod_base; + + +/* +================= +Mod_LoadTextures +================= +*/ +void Mod_LoadTextures (lump_t *l) +{ + int i, j, pixels, num, max, altmax; + miptex_t *mt; + texture_t *tx, *tx2; + texture_t *anims[10]; + texture_t *altanims[10]; + dmiptexlump_t *m; + + if (!l->filelen) + { + loadmodel->textures = NULL; + return; + } + m = (dmiptexlump_t *)(mod_base + l->fileofs); + + m->nummiptex = LittleLong (m->nummiptex); + + loadmodel->numtextures = m->nummiptex; + loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); + + for (i=0 ; inummiptex ; i++) + { + m->dataofs[i] = LittleLong(m->dataofs[i]); + if (m->dataofs[i] == -1) + continue; + mt = (miptex_t *)((byte *)m + m->dataofs[i]); + mt->width = LittleLong (mt->width); + mt->height = LittleLong (mt->height); + for (j=0 ; joffsets[j] = LittleLong (mt->offsets[j]); + + if ( (mt->width & 15) || (mt->height & 15) ) + Sys_Error ("Texture %s is not 16 aligned", mt->name); + pixels = mt->width*mt->height/64*85; + tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); + loadmodel->textures[i] = tx; + + memcpy (tx->name, mt->name, sizeof(tx->name)); + tx->width = mt->width; + tx->height = mt->height; + for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); + // the pixels immediately follow the structures + memcpy ( tx+1, mt+1, pixels); + + if (!Q_strncmp(mt->name,"sky",3)) + R_InitSky (tx); + } + +// +// sequence the animations +// + for (i=0 ; inummiptex ; i++) + { + tx = loadmodel->textures[i]; + if (!tx || tx->name[0] != '+') + continue; + if (tx->anim_next) + continue; // allready sequenced + + // find the number of frames in the animation + memset (anims, 0, sizeof(anims)); + memset (altanims, 0, sizeof(altanims)); + + max = tx->name[1]; + altmax = 0; + if (max >= 'a' && max <= 'z') + max -= 'a' - 'A'; + if (max >= '0' && max <= '9') + { + max -= '0'; + altmax = 0; + anims[max] = tx; + max++; + } + else if (max >= 'A' && max <= 'J') + { + altmax = max - 'A'; + max = 0; + altanims[altmax] = tx; + altmax++; + } + else + Sys_Error ("Bad animating texture %s", tx->name); + + for (j=i+1 ; jnummiptex ; j++) + { + tx2 = loadmodel->textures[j]; + if (!tx2 || tx2->name[0] != '+') + continue; + if (strcmp (tx2->name+2, tx->name+2)) + continue; + + num = tx2->name[1]; + if (num >= 'a' && num <= 'z') + num -= 'a' - 'A'; + if (num >= '0' && num <= '9') + { + num -= '0'; + anims[num] = tx2; + if (num+1 > max) + max = num + 1; + } + else if (num >= 'A' && num <= 'J') + { + num = num - 'A'; + altanims[num] = tx2; + if (num+1 > altmax) + altmax = num+1; + } + else + Sys_Error ("Bad animating texture %s", tx->name); + } + +#define ANIM_CYCLE 2 + // link them all together + for (j=0 ; jname); + tx2->anim_total = max * ANIM_CYCLE; + tx2->anim_min = j * ANIM_CYCLE; + tx2->anim_max = (j+1) * ANIM_CYCLE; + tx2->anim_next = anims[ (j+1)%max ]; + if (altmax) + tx2->alternate_anims = altanims[0]; + } + for (j=0 ; jname); + tx2->anim_total = altmax * ANIM_CYCLE; + tx2->anim_min = j * ANIM_CYCLE; + tx2->anim_max = (j+1) * ANIM_CYCLE; + tx2->anim_next = altanims[ (j+1)%altmax ]; + if (max) + tx2->alternate_anims = anims[0]; + } + } +} + +/* +================= +Mod_LoadLighting +================= +*/ +void Mod_LoadLighting (lump_t *l) +{ + if (!l->filelen) + { + loadmodel->lightdata = NULL; + return; + } + loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); + memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); +} + + +/* +================= +Mod_LoadVisibility +================= +*/ +void Mod_LoadVisibility (lump_t *l) +{ + if (!l->filelen) + { + loadmodel->visdata = NULL; + return; + } + loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); + memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); +} + + +/* +================= +Mod_LoadEntities +================= +*/ +void Mod_LoadEntities (lump_t *l) +{ + if (!l->filelen) + { + loadmodel->entities = NULL; + return; + } + loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); + memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); +} + + +/* +================= +Mod_LoadVertexes +================= +*/ +void Mod_LoadVertexes (lump_t *l) +{ + dvertex_t *in; + mvertex_t *out; + int i, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->vertexes = out; + loadmodel->numvertexes = count; + + for ( i=0 ; iposition[0] = LittleFloat (in->point[0]); + out->position[1] = LittleFloat (in->point[1]); + out->position[2] = LittleFloat (in->point[2]); + } +} + +/* +================= +Mod_LoadSubmodels +================= +*/ +void Mod_LoadSubmodels (lump_t *l) +{ + dmodel_t *in; + dmodel_t *out; + int i, j, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->submodels = out; + loadmodel->numsubmodels = count; + + for ( i=0 ; imins[j] = LittleFloat (in->mins[j]) - 1; + out->maxs[j] = LittleFloat (in->maxs[j]) + 1; + out->origin[j] = LittleFloat (in->origin[j]); + } + for (j=0 ; jheadnode[j] = LittleLong (in->headnode[j]); + out->visleafs = LittleLong (in->visleafs); + out->firstface = LittleLong (in->firstface); + out->numfaces = LittleLong (in->numfaces); + } +} + +/* +================= +Mod_LoadEdges +================= +*/ +void Mod_LoadEdges (lump_t *l) +{ + dedge_t *in; + medge_t *out; + int i, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); + out->v[1] = (unsigned short)LittleShort(in->v[1]); + } +} + +/* +================= +Mod_LoadTexinfo +================= +*/ +void Mod_LoadTexinfo (lump_t *l) +{ + texinfo_t *in; + mtexinfo_t *out; + int i, j, count; + int miptex; + float len1, len2; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->texinfo = out; + loadmodel->numtexinfo = count; + + for ( i=0 ; ivecs[0][j] = LittleFloat (in->vecs[0][j]); + len1 = Length (out->vecs[0]); + len2 = Length (out->vecs[1]); + len1 = (len1 + len2)/2; + if (len1 < 0.32) + out->mipadjust = 4; + else if (len1 < 0.49) + out->mipadjust = 3; + else if (len1 < 0.99) + out->mipadjust = 2; + else + out->mipadjust = 1; +#if 0 + if (len1 + len2 < 0.001) + out->mipadjust = 1; // don't crash + else + out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); +#endif + + miptex = LittleLong (in->miptex); + out->flags = LittleLong (in->flags); + + if (!loadmodel->textures) + { + out->texture = r_notexture_mip; // checkerboard texture + out->flags = 0; + } + else + { + if (miptex >= loadmodel->numtextures) + Sys_Error ("miptex >= loadmodel->numtextures"); + out->texture = loadmodel->textures[miptex]; + if (!out->texture) + { + out->texture = r_notexture_mip; // texture not found + out->flags = 0; + } + } + } +} + +/* +================ +CalcSurfaceExtents + +Fills in s->texturemins[] and s->extents[] +================ +*/ +void CalcSurfaceExtents (msurface_t *s) +{ + float mins[2], maxs[2], val; + int i,j, e; + mvertex_t *v; + mtexinfo_t *tex; + int bmins[2], bmaxs[2]; + + mins[0] = mins[1] = 999999; + maxs[0] = maxs[1] = -99999; + + tex = s->texinfo; + + for (i=0 ; inumedges ; i++) + { + e = loadmodel->surfedges[s->firstedge+i]; + if (e >= 0) + v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; + else + v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; + + for (j=0 ; j<2 ; j++) + { + val = v->position[0] * tex->vecs[j][0] + + v->position[1] * tex->vecs[j][1] + + v->position[2] * tex->vecs[j][2] + + tex->vecs[j][3]; + if (val < mins[j]) + mins[j] = val; + if (val > maxs[j]) + maxs[j] = val; + } + } + + for (i=0 ; i<2 ; i++) + { + bmins[i] = floor(mins[i]/16); + bmaxs[i] = ceil(maxs[i]/16); + + s->texturemins[i] = bmins[i] * 16; + s->extents[i] = (bmaxs[i] - bmins[i]) * 16; + if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256) + Sys_Error ("Bad surface extents"); + } +} + + +/* +================= +Mod_LoadFaces +================= +*/ +void Mod_LoadFaces (lump_t *l) +{ + dface_t *in; + msurface_t *out; + int i, count, surfnum; + int planenum, side; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->surfaces = out; + loadmodel->numsurfaces = count; + + for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); + out->numedges = LittleShort(in->numedges); + out->flags = 0; + + planenum = LittleShort(in->planenum); + side = LittleShort(in->side); + if (side) + out->flags |= SURF_PLANEBACK; + + out->plane = loadmodel->planes + planenum; + + out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); + + CalcSurfaceExtents (out); + + // lighting info + + for (i=0 ; istyles[i] = in->styles[i]; + i = LittleLong(in->lightofs); + if (i == -1) + out->samples = NULL; + else + out->samples = loadmodel->lightdata + i; + + // set the drawing flags flag + + if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky + { + out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); + continue; + } + + if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent + { + out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); + for (i=0 ; i<2 ; i++) + { + out->extents[i] = 16384; + out->texturemins[i] = -8192; + } + continue; + } + } +} + + +/* +================= +Mod_SetParent +================= +*/ +void Mod_SetParent (mnode_t *node, mnode_t *parent) +{ + node->parent = parent; + if (node->contents < 0) + return; + Mod_SetParent (node->children[0], node); + Mod_SetParent (node->children[1], node); +} + +/* +================= +Mod_LoadNodes +================= +*/ +void Mod_LoadNodes (lump_t *l) +{ + int i, j, count, p; + dnode_t *in; + mnode_t *out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleShort (in->firstface); + out->numsurfaces = LittleShort (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleShort (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } + } + + Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs +} + +/* +================= +Mod_LoadLeafs +================= +*/ +void Mod_LoadLeafs (lump_t *l) +{ + dleaf_t *in; + mleaf_t *out; + int i, j, count, p; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->leafs = out; + loadmodel->numleafs = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + LittleShort(in->firstmarksurface); + out->nummarksurfaces = LittleShort(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + out->efrags = NULL; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + } +} + +/* +================= +Mod_LoadClipnodes +================= +*/ +void Mod_LoadClipnodes (lump_t *l) +{ + dclipnode_t *in, *out; + int i, count; + hull_t *hull; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->clipnodes = out; + loadmodel->numclipnodes = count; + + hull = &loadmodel->hulls[1]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 32; + + hull = &loadmodel->hulls[2]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -32; + hull->clip_mins[1] = -32; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 32; + hull->clip_maxs[1] = 32; + hull->clip_maxs[2] = 64; + + for (i=0 ; iplanenum = LittleLong(in->planenum); + out->children[0] = LittleShort(in->children[0]); + out->children[1] = LittleShort(in->children[1]); + } +} + +/* +================= +Mod_MakeHull0 + +Deplicate the drawing hull structure as a clipping hull +================= +*/ +void Mod_MakeHull0 (void) +{ + mnode_t *in, *child; + dclipnode_t *out; + int i, j, count; + hull_t *hull; + + hull = &loadmodel->hulls[0]; + + in = loadmodel->nodes; + count = loadmodel->numnodes; + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + + for (i=0 ; iplanenum = in->plane - loadmodel->planes; + for (j=0 ; j<2 ; j++) + { + child = in->children[j]; + if (child->contents < 0) + out->children[j] = child->contents; + else + out->children[j] = child - loadmodel->nodes; + } + } +} + +/* +================= +Mod_LoadMarksurfaces +================= +*/ +void Mod_LoadMarksurfaces (lump_t *l) +{ + int i, j, count; + short *in; + msurface_t **out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->marksurfaces = out; + loadmodel->nummarksurfaces = count; + + for ( i=0 ; i= loadmodel->numsurfaces) + Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); + out[i] = loadmodel->surfaces + j; + } +} + +/* +================= +Mod_LoadSurfedges +================= +*/ +void Mod_LoadSurfedges (lump_t *l) +{ + int i, count; + int *in, *out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->surfedges = out; + loadmodel->numsurfedges = count; + + for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*2*sizeof(*out), loadname); + + loadmodel->planes = out; + loadmodel->numplanes = count; + + for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); + if (out->normal[j] < 0) + bits |= 1<dist = LittleFloat (in->dist); + out->type = LittleLong (in->type); + out->signbits = bits; + } +} + +/* +================= +RadiusFromBounds +================= +*/ +float RadiusFromBounds (vec3_t mins, vec3_t maxs) +{ + int i; + vec3_t corner; + + for (i=0 ; i<3 ; i++) + { + corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); + } + + return Length (corner); +} + +/* +================= +Mod_LoadBrushModel +================= +*/ +void Mod_LoadBrushModel (model_t *mod, void *buffer) +{ + int i, j; + dheader_t *header; + dmodel_t *bm; + + loadmodel->type = mod_brush; + + header = (dheader_t *)buffer; + + i = LittleLong (header->version); + if (i != BSPVERSION) + Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); + +// swap all the lumps + mod_base = (byte *)header; + + for (i=0 ; ilumps[LUMP_VERTEXES]); + Mod_LoadEdges (&header->lumps[LUMP_EDGES]); + Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); + Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); + Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); + Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); + Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); + Mod_LoadFaces (&header->lumps[LUMP_FACES]); + Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); + Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); + Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); + Mod_LoadNodes (&header->lumps[LUMP_NODES]); + Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); + Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); + Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); + + Mod_MakeHull0 (); + + mod->numframes = 2; // regular and alternate animation + mod->flags = 0; + +// +// set up the submodels (FIXME: this is confusing) +// + for (i=0 ; inumsubmodels ; i++) + { + bm = &mod->submodels[i]; + + mod->hulls[0].firstclipnode = bm->headnode[0]; + for (j=1 ; jhulls[j].firstclipnode = bm->headnode[j]; + mod->hulls[j].lastclipnode = mod->numclipnodes-1; + } + + mod->firstmodelsurface = bm->firstface; + mod->nummodelsurfaces = bm->numfaces; + + VectorCopy (bm->maxs, mod->maxs); + VectorCopy (bm->mins, mod->mins); + mod->radius = RadiusFromBounds (mod->mins, mod->maxs); + + mod->numleafs = bm->visleafs; + + if (i < mod->numsubmodels-1) + { // duplicate the basic information + char name[10]; + + sprintf (name, "*%i", i+1); + loadmodel = Mod_FindName (name); + *loadmodel = *mod; + strcpy (loadmodel->name, name); + mod = loadmodel; + } + } +} + +/* +============================================================================== + +ALIAS MODELS + +============================================================================== +*/ + +/* +================= +Mod_LoadAliasFrame +================= +*/ +void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv, + trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name) +{ + trivertx_t *pframe, *pinframe; + int i, j; + daliasframe_t *pdaliasframe; + + pdaliasframe = (daliasframe_t *)pin; + + strcpy (name, pdaliasframe->name); + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about + // endianness + pbboxmin->v[i] = pdaliasframe->bboxmin.v[i]; + pbboxmax->v[i] = pdaliasframe->bboxmax.v[i]; + } + + pinframe = (trivertx_t *)(pdaliasframe + 1); + pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname); + + *pframeindex = (byte *)pframe - (byte *)pheader; + + for (j=0 ; jnumframes); + + paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) + + (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname); + + paliasgroup->numframes = numframes; + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about endianness + pbboxmin->v[i] = pingroup->bboxmin.v[i]; + pbboxmax->v[i] = pingroup->bboxmax.v[i]; + } + + *pframeindex = (byte *)paliasgroup - (byte *)pheader; + + pin_intervals = (daliasinterval_t *)(pingroup + 1); + + poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + + paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader; + + for (i=0 ; iinterval); + if (*poutintervals <= 0.0) + Sys_Error ("Mod_LoadAliasGroup: interval<=0"); + + poutintervals++; + pin_intervals++; + } + + ptemp = (void *)pin_intervals; + + for (i=0 ; iframes[i].frame, + numv, + &paliasgroup->frames[i].bboxmin, + &paliasgroup->frames[i].bboxmax, + pheader, name); + } + + return ptemp; +} + + +/* +================= +Mod_LoadAliasSkin +================= +*/ +void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize, + aliashdr_t *pheader) +{ + int i; + byte *pskin, *pinskin; + unsigned short *pusskin; + + pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); + pinskin = (byte *)pin; + *pskinindex = (byte *)pskin - (byte *)pheader; + + if (r_pixbytes == 1) + { + Q_memcpy (pskin, pinskin, skinsize); + } + else if (r_pixbytes == 2) + { + pusskin = (unsigned short *)pskin; + + for (i=0 ; inumskins); + + paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) + + (numskins - 1) * sizeof (paliasskingroup->skindescs[0]), + loadname); + + paliasskingroup->numskins = numskins; + + *pskinindex = (byte *)paliasskingroup - (byte *)pheader; + + pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); + + poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname); + + paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader; + + for (i=0 ; iinterval); + if (*poutskinintervals <= 0) + Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); + + poutskinintervals++; + pinskinintervals++; + } + + ptemp = (void *)pinskinintervals; + + for (i=0 ; iskindescs[i].skin, skinsize, pheader); + } + + return ptemp; +} + + +/* +================= +Mod_LoadAliasModel +================= +*/ +void Mod_LoadAliasModel (model_t *mod, void *buffer) +{ + int i; + mdl_t *pmodel, *pinmodel; + stvert_t *pstverts, *pinstverts; + aliashdr_t *pheader; + mtriangle_t *ptri; + dtriangle_t *pintriangles; + int version, numframes, numskins; + int size; + daliasframetype_t *pframetype; + daliasskintype_t *pskintype; + maliasskindesc_t *pskindesc; + int skinsize; + int start, end, total; + + start = Hunk_LowMark (); + + pinmodel = (mdl_t *)buffer; + + version = LittleLong (pinmodel->version); + if (version != ALIAS_VERSION) + Sys_Error ("%s has wrong version number (%i should be %i)", + mod->name, version, ALIAS_VERSION); + +// +// allocate space for a working header, plus all the data except the frames, +// skin and group info +// + size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * + sizeof (pheader->frames[0]) + + sizeof (mdl_t) + + LittleLong (pinmodel->numverts) * sizeof (stvert_t) + + LittleLong (pinmodel->numtris) * sizeof (mtriangle_t); + + pheader = Hunk_AllocName (size, loadname); + pmodel = (mdl_t *) ((byte *)&pheader[1] + + (LittleLong (pinmodel->numframes) - 1) * + sizeof (pheader->frames[0])); + +// mod->cache.data = pheader; + mod->flags = LittleLong (pinmodel->flags); + +// +// endian-adjust and copy the data, starting with the alias model header +// + pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); + pmodel->numskins = LittleLong (pinmodel->numskins); + pmodel->skinwidth = LittleLong (pinmodel->skinwidth); + pmodel->skinheight = LittleLong (pinmodel->skinheight); + + if (pmodel->skinheight > MAX_LBM_HEIGHT) + Sys_Error ("model %s has a skin taller than %d", mod->name, + MAX_LBM_HEIGHT); + + pmodel->numverts = LittleLong (pinmodel->numverts); + + if (pmodel->numverts <= 0) + Sys_Error ("model %s has no vertices", mod->name); + + if (pmodel->numverts > MAXALIASVERTS) + Sys_Error ("model %s has too many vertices", mod->name); + + pmodel->numtris = LittleLong (pinmodel->numtris); + + if (pmodel->numtris <= 0) + Sys_Error ("model %s has no triangles", mod->name); + + pmodel->numframes = LittleLong (pinmodel->numframes); + pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; + mod->synctype = LittleLong (pinmodel->synctype); + mod->numframes = pmodel->numframes; + + for (i=0 ; i<3 ; i++) + { + pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); + pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); + pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); + } + + numskins = pmodel->numskins; + numframes = pmodel->numframes; + + if (pmodel->skinwidth & 0x03) + Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4"); + + pheader->model = (byte *)pmodel - (byte *)pheader; + +// +// load the skins +// + skinsize = pmodel->skinheight * pmodel->skinwidth; + + if (numskins < 1) + Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); + + pskintype = (daliasskintype_t *)&pinmodel[1]; + + pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), + loadname); + + pheader->skindesc = (byte *)pskindesc - (byte *)pheader; + + for (i=0 ; itype); + pskindesc[i].type = skintype; + + if (skintype == ALIAS_SKIN_SINGLE) + { + pskintype = (daliasskintype_t *) + Mod_LoadAliasSkin (pskintype + 1, + &pskindesc[i].skin, + skinsize, pheader); + } + else + { + pskintype = (daliasskintype_t *) + Mod_LoadAliasSkinGroup (pskintype + 1, + &pskindesc[i].skin, + skinsize, pheader); + } + } + +// +// set base s and t vertices +// + pstverts = (stvert_t *)&pmodel[1]; + pinstverts = (stvert_t *)pskintype; + + pheader->stverts = (byte *)pstverts - (byte *)pheader; + + for (i=0 ; inumverts ; i++) + { + pstverts[i].onseam = LittleLong (pinstverts[i].onseam); + // put s and t in 16.16 format + pstverts[i].s = LittleLong (pinstverts[i].s) << 16; + pstverts[i].t = LittleLong (pinstverts[i].t) << 16; + } + +// +// set up the triangles +// + ptri = (mtriangle_t *)&pstverts[pmodel->numverts]; + pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts]; + + pheader->triangles = (byte *)ptri - (byte *)pheader; + + for (i=0 ; inumtris ; i++) + { + int j; + + ptri[i].facesfront = LittleLong (pintriangles[i].facesfront); + + for (j=0 ; j<3 ; j++) + { + ptri[i].vertindex[j] = + LittleLong (pintriangles[i].vertindex[j]); + } + } + +// +// load the frames +// + if (numframes < 1) + Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); + + pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; + + for (i=0 ; itype); + pheader->frames[i].type = frametype; + + if (frametype == ALIAS_SINGLE) + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasFrame (pframetype + 1, + &pheader->frames[i].frame, + pmodel->numverts, + &pheader->frames[i].bboxmin, + &pheader->frames[i].bboxmax, + pheader, pheader->frames[i].name); + } + else + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasGroup (pframetype + 1, + &pheader->frames[i].frame, + pmodel->numverts, + &pheader->frames[i].bboxmin, + &pheader->frames[i].bboxmax, + pheader, pheader->frames[i].name); + } + } + + mod->type = mod_alias; + +// FIXME: do this right + mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; + mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; + +// +// move the complete, relocatable alias model to the cache +// + end = Hunk_LowMark (); + total = end - start; + + Cache_Alloc (&mod->cache, total, loadname); + if (!mod->cache.data) + return; + memcpy (mod->cache.data, pheader, total); + + Hunk_FreeToLowMark (start); +} + +//============================================================================= + +/* +================= +Mod_LoadSpriteFrame +================= +*/ +void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe) +{ + dspriteframe_t *pinframe; + mspriteframe_t *pspriteframe; + int i, width, height, size, origin[2]; + unsigned short *ppixout; + byte *ppixin; + + pinframe = (dspriteframe_t *)pin; + + width = LittleLong (pinframe->width); + height = LittleLong (pinframe->height); + size = width * height; + + pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes, + loadname); + + Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); + *ppframe = pspriteframe; + + pspriteframe->width = width; + pspriteframe->height = height; + origin[0] = LittleLong (pinframe->origin[0]); + origin[1] = LittleLong (pinframe->origin[1]); + + pspriteframe->up = origin[1]; + pspriteframe->down = origin[1] - height; + pspriteframe->left = origin[0]; + pspriteframe->right = width + origin[0]; + + if (r_pixbytes == 1) + { + Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size); + } + else if (r_pixbytes == 2) + { + ppixin = (byte *)(pinframe + 1); + ppixout = (unsigned short *)&pspriteframe->pixels[0]; + + for (i=0 ; inumframes); + + pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + + (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); + + pspritegroup->numframes = numframes; + + *ppframe = (mspriteframe_t *)pspritegroup; + + pin_intervals = (dspriteinterval_t *)(pingroup + 1); + + poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + + pspritegroup->intervals = poutintervals; + + for (i=0 ; iinterval); + if (*poutintervals <= 0.0) + Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); + + poutintervals++; + pin_intervals++; + } + + ptemp = (void *)pin_intervals; + + for (i=0 ; iframes[i]); + } + + return ptemp; +} + + +/* +================= +Mod_LoadSpriteModel +================= +*/ +void Mod_LoadSpriteModel (model_t *mod, void *buffer) +{ + int i; + int version; + dsprite_t *pin; + msprite_t *psprite; + int numframes; + int size; + dspriteframetype_t *pframetype; + + pin = (dsprite_t *)buffer; + + version = LittleLong (pin->version); + if (version != SPRITE_VERSION) + Sys_Error ("%s has wrong version number " + "(%i should be %i)", mod->name, version, SPRITE_VERSION); + + numframes = LittleLong (pin->numframes); + + size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); + + psprite = Hunk_AllocName (size, loadname); + + mod->cache.data = psprite; + + psprite->type = LittleLong (pin->type); + psprite->maxwidth = LittleLong (pin->width); + psprite->maxheight = LittleLong (pin->height); + psprite->beamlength = LittleFloat (pin->beamlength); + mod->synctype = LittleLong (pin->synctype); + psprite->numframes = numframes; + + mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; + mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; + mod->mins[2] = -psprite->maxheight/2; + mod->maxs[2] = psprite->maxheight/2; + +// +// load the frames +// + if (numframes < 1) + Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); + + mod->numframes = numframes; + mod->flags = 0; + + pframetype = (dspriteframetype_t *)(pin + 1); + + for (i=0 ; itype); + psprite->frames[i].type = frametype; + + if (frametype == SPR_SINGLE) + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteFrame (pframetype + 1, + &psprite->frames[i].frameptr); + } + else + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteGroup (pframetype + 1, + &psprite->frames[i].frameptr); + } + } + + mod->type = mod_sprite; +} + +//============================================================================= + +/* +================ +Mod_Print +================ +*/ +void Mod_Print (void) +{ + int i; + model_t *mod; + + Con_Printf ("Cached models:\n"); + for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) + { + Con_Printf ("%8p : %s",mod->cache.data, mod->name); + if (mod->needload & NL_UNREFERENCED) + Con_Printf (" (!R)"); + if (mod->needload & NL_NEEDS_LOADED) + Con_Printf (" (!P)"); + Con_Printf ("\n"); + } +} + + diff --git a/WinQuake/model.h b/WinQuake/model.h index 2e89862..312a1f1 100644 --- a/WinQuake/model.h +++ b/WinQuake/model.h @@ -1,382 +1,382 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#ifndef __MODEL__ -#define __MODEL__ - -#include "modelgen.h" -#include "spritegn.h" - -/* - -d*_t structures are on-disk representations -m*_t structures are in-memory - -*/ - -/* -============================================================================== - -BRUSH MODELS - -============================================================================== -*/ - - -// -// in memory representation -// -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct -{ - vec3_t position; -} mvertex_t; - -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 - - -// plane_t structure -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct mplane_s -{ - vec3_t normal; - float dist; - byte type; // for texture axis selection and fast side tests - byte signbits; // signx + signy<<1 + signz<<1 - byte pad[2]; -} mplane_t; - -typedef struct texture_s -{ - char name[16]; - unsigned width, height; - int anim_total; // total tenths in sequence ( 0 = no) - int anim_min, anim_max; // time for this frame min <=time< max - struct texture_s *anim_next; // in the animation sequence - struct texture_s *alternate_anims; // bmodels in frmae 1 use these - unsigned offsets[MIPLEVELS]; // four mip maps stored -} texture_t; - - -#define SURF_PLANEBACK 2 -#define SURF_DRAWSKY 4 -#define SURF_DRAWSPRITE 8 -#define SURF_DRAWTURB 0x10 -#define SURF_DRAWTILED 0x20 -#define SURF_DRAWBACKGROUND 0x40 - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct -{ - unsigned short v[2]; - unsigned int cachededgeoffset; -} medge_t; - -typedef struct -{ - float vecs[2][4]; - float mipadjust; - texture_t *texture; - int flags; -} mtexinfo_t; - -typedef struct msurface_s -{ - int visframe; // should be drawn when node is crossed - - int dlightframe; - int dlightbits; - - mplane_t *plane; - int flags; - - int firstedge; // look up in model->surfedges[], negative numbers - int numedges; // are backwards edges - -// surface generation data - struct surfcache_s *cachespots[MIPLEVELS]; - - short texturemins[2]; - short extents[2]; - - mtexinfo_t *texinfo; - -// lighting info - byte styles[MAXLIGHTMAPS]; - byte *samples; // [numstyles*surfsize] -} msurface_t; - -typedef struct mnode_s -{ -// common with leaf - int contents; // 0, to differentiate from leafs - int visframe; // node needs to be traversed if current - - short minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// node specific - mplane_t *plane; - struct mnode_s *children[2]; - - unsigned short firstsurface; - unsigned short numsurfaces; -} mnode_t; - - - -typedef struct mleaf_s -{ -// common with node - int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current - - short minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// leaf specific - byte *compressed_vis; - efrag_t *efrags; - - msurface_t **firstmarksurface; - int nummarksurfaces; - int key; // BSP sequence number for leaf's contents - byte ambient_sound_level[NUM_AMBIENTS]; -} mleaf_t; - -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct -{ - dclipnode_t *clipnodes; - mplane_t *planes; - int firstclipnode; - int lastclipnode; - vec3_t clip_mins; - vec3_t clip_maxs; -} hull_t; - -/* -============================================================================== - -SPRITE MODELS - -============================================================================== -*/ - - -// FIXME: shorten these? -typedef struct mspriteframe_s -{ - int width; - int height; - void *pcachespot; // remove? - float up, down, left, right; - byte pixels[4]; -} mspriteframe_t; - -typedef struct -{ - int numframes; - float *intervals; - mspriteframe_t *frames[1]; -} mspritegroup_t; - -typedef struct -{ - spriteframetype_t type; - mspriteframe_t *frameptr; -} mspriteframedesc_t; - -typedef struct -{ - int type; - int maxwidth; - int maxheight; - int numframes; - float beamlength; // remove? - void *cachespot; // remove? - mspriteframedesc_t frames[1]; -} msprite_t; - - -/* -============================================================================== - -ALIAS MODELS - -Alias models are position independent, so the cache manager can move them. -============================================================================== -*/ - -typedef struct -{ - aliasframetype_t type; - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; - char name[16]; -} maliasframedesc_t; - -typedef struct -{ - aliasskintype_t type; - void *pcachespot; - int skin; -} maliasskindesc_t; - -typedef struct -{ - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; -} maliasgroupframedesc_t; - -typedef struct -{ - int numframes; - int intervals; - maliasgroupframedesc_t frames[1]; -} maliasgroup_t; - -typedef struct -{ - int numskins; - int intervals; - maliasskindesc_t skindescs[1]; -} maliasskingroup_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct mtriangle_s { - int facesfront; - int vertindex[3]; -} mtriangle_t; - -typedef struct { - int model; - int stverts; - int skindesc; - int triangles; - maliasframedesc_t frames[1]; -} aliashdr_t; - -//=================================================================== - -// -// Whole model -// - -typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; - -#define EF_ROCKET 1 // leave a trail -#define EF_GRENADE 2 // leave a trail -#define EF_GIB 4 // leave a trail -#define EF_ROTATE 8 // rotate (bonus items) -#define EF_TRACER 16 // green split trail -#define EF_ZOMGIB 32 // small blood trail -#define EF_TRACER2 64 // orange split trail + rotate -#define EF_TRACER3 128 // purple trail - -typedef struct model_s -{ - char name[MAX_QPATH]; - qboolean needload; // bmodels and sprites don't cache normally - - modtype_t type; - int numframes; - synctype_t synctype; - - int flags; - -// -// volume occupied by the model -// - vec3_t mins, maxs; - float radius; - -// -// brush model -// - int firstmodelsurface, nummodelsurfaces; - - int numsubmodels; - dmodel_t *submodels; - - int numplanes; - mplane_t *planes; - - int numleafs; // number of visible leafs, not counting 0 - mleaf_t *leafs; - - int numvertexes; - mvertex_t *vertexes; - - int numedges; - medge_t *edges; - - int numnodes; - mnode_t *nodes; - - int numtexinfo; - mtexinfo_t *texinfo; - - int numsurfaces; - msurface_t *surfaces; - - int numsurfedges; - int *surfedges; - - int numclipnodes; - dclipnode_t *clipnodes; - - int nummarksurfaces; - msurface_t **marksurfaces; - - hull_t hulls[MAX_MAP_HULLS]; - - int numtextures; - texture_t **textures; - - byte *visdata; - byte *lightdata; - char *entities; - -// -// additional model data -// - cache_user_t cache; // only access through Mod_Extradata - -} model_t; - -//============================================================================ - -void Mod_Init (void); -void Mod_ClearAll (void); -model_t *Mod_ForName (char *name, qboolean crash); -void *Mod_Extradata (model_t *mod); // handles caching -void Mod_TouchModel (char *name); - -mleaf_t *Mod_PointInLeaf (float *p, model_t *model); -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); - -#endif // __MODEL__ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __MODEL__ +#define __MODEL__ + +#include "modelgen.h" +#include "spritegn.h" + +/* + +d*_t structures are on-disk representations +m*_t structures are in-memory + +*/ + +/* +============================================================================== + +BRUSH MODELS + +============================================================================== +*/ + + +// +// in memory representation +// +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + vec3_t position; +} mvertex_t; + +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 + + +// plane_t structure +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct mplane_s +{ + vec3_t normal; + float dist; + byte type; // for texture axis selection and fast side tests + byte signbits; // signx + signy<<1 + signz<<1 + byte pad[2]; +} mplane_t; + +typedef struct texture_s +{ + char name[16]; + unsigned width, height; + int anim_total; // total tenths in sequence ( 0 = no) + int anim_min, anim_max; // time for this frame min <=time< max + struct texture_s *anim_next; // in the animation sequence + struct texture_s *alternate_anims; // bmodels in frmae 1 use these + unsigned offsets[MIPLEVELS]; // four mip maps stored +} texture_t; + + +#define SURF_PLANEBACK 2 +#define SURF_DRAWSKY 4 +#define SURF_DRAWSPRITE 8 +#define SURF_DRAWTURB 0x10 +#define SURF_DRAWTILED 0x20 +#define SURF_DRAWBACKGROUND 0x40 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + unsigned short v[2]; + unsigned int cachededgeoffset; +} medge_t; + +typedef struct +{ + float vecs[2][4]; + float mipadjust; + texture_t *texture; + int flags; +} mtexinfo_t; + +typedef struct msurface_s +{ + int visframe; // should be drawn when node is crossed + + int dlightframe; + int dlightbits; + + mplane_t *plane; + int flags; + + int firstedge; // look up in model->surfedges[], negative numbers + int numedges; // are backwards edges + +// surface generation data + struct surfcache_s *cachespots[MIPLEVELS]; + + short texturemins[2]; + short extents[2]; + + mtexinfo_t *texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + byte *samples; // [numstyles*surfsize] +} msurface_t; + +typedef struct mnode_s +{ +// common with leaf + int contents; // 0, to differentiate from leafs + int visframe; // node needs to be traversed if current + + short minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// node specific + mplane_t *plane; + struct mnode_s *children[2]; + + unsigned short firstsurface; + unsigned short numsurfaces; +} mnode_t; + + + +typedef struct mleaf_s +{ +// common with node + int contents; // wil be a negative contents number + int visframe; // node needs to be traversed if current + + short minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// leaf specific + byte *compressed_vis; + efrag_t *efrags; + + msurface_t **firstmarksurface; + int nummarksurfaces; + int key; // BSP sequence number for leaf's contents + byte ambient_sound_level[NUM_AMBIENTS]; +} mleaf_t; + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + dclipnode_t *clipnodes; + mplane_t *planes; + int firstclipnode; + int lastclipnode; + vec3_t clip_mins; + vec3_t clip_maxs; +} hull_t; + +/* +============================================================================== + +SPRITE MODELS + +============================================================================== +*/ + + +// FIXME: shorten these? +typedef struct mspriteframe_s +{ + int width; + int height; + void *pcachespot; // remove? + float up, down, left, right; + byte pixels[4]; +} mspriteframe_t; + +typedef struct +{ + int numframes; + float *intervals; + mspriteframe_t *frames[1]; +} mspritegroup_t; + +typedef struct +{ + spriteframetype_t type; + mspriteframe_t *frameptr; +} mspriteframedesc_t; + +typedef struct +{ + int type; + int maxwidth; + int maxheight; + int numframes; + float beamlength; // remove? + void *cachespot; // remove? + mspriteframedesc_t frames[1]; +} msprite_t; + + +/* +============================================================================== + +ALIAS MODELS + +Alias models are position independent, so the cache manager can move them. +============================================================================== +*/ + +typedef struct +{ + aliasframetype_t type; + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; + char name[16]; +} maliasframedesc_t; + +typedef struct +{ + aliasskintype_t type; + void *pcachespot; + int skin; +} maliasskindesc_t; + +typedef struct +{ + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; +} maliasgroupframedesc_t; + +typedef struct +{ + int numframes; + int intervals; + maliasgroupframedesc_t frames[1]; +} maliasgroup_t; + +typedef struct +{ + int numskins; + int intervals; + maliasskindesc_t skindescs[1]; +} maliasskingroup_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct mtriangle_s { + int facesfront; + int vertindex[3]; +} mtriangle_t; + +typedef struct { + int model; + int stverts; + int skindesc; + int triangles; + maliasframedesc_t frames[1]; +} aliashdr_t; + +//=================================================================== + +// +// Whole model +// + +typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; + +#define EF_ROCKET 1 // leave a trail +#define EF_GRENADE 2 // leave a trail +#define EF_GIB 4 // leave a trail +#define EF_ROTATE 8 // rotate (bonus items) +#define EF_TRACER 16 // green split trail +#define EF_ZOMGIB 32 // small blood trail +#define EF_TRACER2 64 // orange split trail + rotate +#define EF_TRACER3 128 // purple trail + +typedef struct model_s +{ + char name[MAX_QPATH]; + qboolean needload; // bmodels and sprites don't cache normally + + modtype_t type; + int numframes; + synctype_t synctype; + + int flags; + +// +// volume occupied by the model +// + vec3_t mins, maxs; + float radius; + +// +// brush model +// + int firstmodelsurface, nummodelsurfaces; + + int numsubmodels; + dmodel_t *submodels; + + int numplanes; + mplane_t *planes; + + int numleafs; // number of visible leafs, not counting 0 + mleaf_t *leafs; + + int numvertexes; + mvertex_t *vertexes; + + int numedges; + medge_t *edges; + + int numnodes; + mnode_t *nodes; + + int numtexinfo; + mtexinfo_t *texinfo; + + int numsurfaces; + msurface_t *surfaces; + + int numsurfedges; + int *surfedges; + + int numclipnodes; + dclipnode_t *clipnodes; + + int nummarksurfaces; + msurface_t **marksurfaces; + + hull_t hulls[MAX_MAP_HULLS]; + + int numtextures; + texture_t **textures; + + byte *visdata; + byte *lightdata; + char *entities; + +// +// additional model data +// + cache_user_t cache; // only access through Mod_Extradata + +} model_t; + +//============================================================================ + +void Mod_Init (void); +void Mod_ClearAll (void); +model_t *Mod_ForName (char *name, qboolean crash); +void *Mod_Extradata (model_t *mod); // handles caching +void Mod_TouchModel (char *name); + +mleaf_t *Mod_PointInLeaf (float *p, model_t *model); +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); + +#endif // __MODEL__ diff --git a/WinQuake/modelgen.h b/WinQuake/modelgen.h index be9ad92..76cb956 100644 --- a/WinQuake/modelgen.h +++ b/WinQuake/modelgen.h @@ -1,134 +1,134 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// modelgen.h: header file for model generation program -// - -// ********************************************************* -// * This file must be identical in the modelgen directory * -// * and in the Quake directory, because it's used to * -// * pass data from one to the other via model files. * -// ********************************************************* - -#ifdef INCLUDELIBS - -#include -#include -#include -#include - -#include "cmdlib.h" -#include "scriplib.h" -#include "trilib.h" -#include "lbmlib.h" -#include "mathlib.h" - -#endif - -#define ALIAS_VERSION 6 - -#define ALIAS_ONSEAM 0x0020 - -// must match definition in spritegn.h -#ifndef SYNCTYPE_T -#define SYNCTYPE_T -typedef enum {ST_SYNC=0, ST_RAND } synctype_t; -#endif - -typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t; - -typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t; - -typedef struct { - int ident; - int version; - vec3_t scale; - vec3_t scale_origin; - float boundingradius; - vec3_t eyeposition; - int numskins; - int skinwidth; - int skinheight; - int numverts; - int numtris; - int numframes; - synctype_t synctype; - int flags; - float size; -} mdl_t; - -// TODO: could be shorts - -typedef struct { - int onseam; - int s; - int t; -} stvert_t; - -typedef struct dtriangle_s { - int facesfront; - int vertindex[3]; -} dtriangle_t; - -#define DT_FACES_FRONT 0x0010 - -// This mirrors trivert_t in trilib.h, is present so Quake knows how to -// load this data - -typedef struct { - byte v[3]; - byte lightnormalindex; -} trivertx_t; - -typedef struct { - trivertx_t bboxmin; // lightnormal isn't used - trivertx_t bboxmax; // lightnormal isn't used - char name[16]; // frame name from grabbing -} daliasframe_t; - -typedef struct { - int numframes; - trivertx_t bboxmin; // lightnormal isn't used - trivertx_t bboxmax; // lightnormal isn't used -} daliasgroup_t; - -typedef struct { - int numskins; -} daliasskingroup_t; - -typedef struct { - float interval; -} daliasinterval_t; - -typedef struct { - float interval; -} daliasskininterval_t; - -typedef struct { - aliasframetype_t type; -} daliasframetype_t; - -typedef struct { - aliasskintype_t type; -} daliasskintype_t; - -#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') - // little-endian "IDPO" - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// modelgen.h: header file for model generation program +// + +// ********************************************************* +// * This file must be identical in the modelgen directory * +// * and in the Quake directory, because it's used to * +// * pass data from one to the other via model files. * +// ********************************************************* + +#ifdef INCLUDELIBS + +#include +#include +#include +#include + +#include "cmdlib.h" +#include "scriplib.h" +#include "trilib.h" +#include "lbmlib.h" +#include "mathlib.h" + +#endif + +#define ALIAS_VERSION 6 + +#define ALIAS_ONSEAM 0x0020 + +// must match definition in spritegn.h +#ifndef SYNCTYPE_T +#define SYNCTYPE_T +typedef enum {ST_SYNC=0, ST_RAND } synctype_t; +#endif + +typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t; + +typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t; + +typedef struct { + int ident; + int version; + vec3_t scale; + vec3_t scale_origin; + float boundingradius; + vec3_t eyeposition; + int numskins; + int skinwidth; + int skinheight; + int numverts; + int numtris; + int numframes; + synctype_t synctype; + int flags; + float size; +} mdl_t; + +// TODO: could be shorts + +typedef struct { + int onseam; + int s; + int t; +} stvert_t; + +typedef struct dtriangle_s { + int facesfront; + int vertindex[3]; +} dtriangle_t; + +#define DT_FACES_FRONT 0x0010 + +// This mirrors trivert_t in trilib.h, is present so Quake knows how to +// load this data + +typedef struct { + byte v[3]; + byte lightnormalindex; +} trivertx_t; + +typedef struct { + trivertx_t bboxmin; // lightnormal isn't used + trivertx_t bboxmax; // lightnormal isn't used + char name[16]; // frame name from grabbing +} daliasframe_t; + +typedef struct { + int numframes; + trivertx_t bboxmin; // lightnormal isn't used + trivertx_t bboxmax; // lightnormal isn't used +} daliasgroup_t; + +typedef struct { + int numskins; +} daliasskingroup_t; + +typedef struct { + float interval; +} daliasinterval_t; + +typedef struct { + float interval; +} daliasskininterval_t; + +typedef struct { + aliasframetype_t type; +} daliasframetype_t; + +typedef struct { + aliasskintype_t type; +} daliasskintype_t; + +#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') + // little-endian "IDPO" + diff --git a/WinQuake/mpdosock.h b/WinQuake/mpdosock.h index 75171f4..e16fbe4 100644 --- a/WinQuake/mpdosock.h +++ b/WinQuake/mpdosock.h @@ -1,797 +1,797 @@ -/* WINSOCK.H--definitions to be used with the WINSOCK.DLL - * Copyright (c) 1993-1995, Microsoft Corp. All rights reserved. - * - * This header file corresponds to version 1.1 of the Windows Sockets specification. - * - * This file includes parts which are Copyright (c) 1982-1986 Regents - * of the University of California. All rights reserved. The - * Berkeley Software License Agreement specifies the terms and - * conditions for redistribution. - * - */ - -#ifndef _WINSOCKAPI_ -#define _WINSOCKAPI_ - -#define FAR -#define PASCAL - -/* - * Basic system type definitions, taken from the BSD file sys/types.h. - */ -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; - -/* - * The new type to be used in all - * instances which refer to sockets. - */ -typedef u_int SOCKET; - -// FIXME -#if 0 -/* - * Select uses arrays of SOCKETs. These macros manipulate such - * arrays. FD_SETSIZE may be defined by the user before including - * this file, but the default here should be >= 64. - * - * CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE - * INCLUDED IN WINSOCK.H EXACTLY AS SHOWN HERE. - */ -#ifndef FD_SETSIZE -#define FD_SETSIZE 64 -#endif /* FD_SETSIZE */ - -typedef struct fd_set { - u_int fd_count; /* how many are SET? */ - SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */ -} fd_set; - -#ifdef __cplusplus -extern "C" { -#endif - -extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *); - -#ifdef __cplusplus -} -#endif - - -#define FD_CLR(fd, set) do { \ - u_int __i; \ - for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \ - if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \ - while (__i < ((fd_set FAR *)(set))->fd_count-1) { \ - ((fd_set FAR *)(set))->fd_array[__i] = \ - ((fd_set FAR *)(set))->fd_array[__i+1]; \ - __i++; \ - } \ - ((fd_set FAR *)(set))->fd_count--; \ - break; \ - } \ - } \ -} while(0) - -#define FD_SET(fd, set) do { \ - if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \ - ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ -} while(0) - -#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0) - -#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set)) - -/* - * Structure used in select() call, taken from the BSD file sys/time.h. - */ -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; - -/* - * Operations on timevals. - * - * NB: timercmp does not work for >= or <=. - */ -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timercmp(tvp, uvp, cmp) \ - ((tvp)->tv_sec cmp (uvp)->tv_sec || \ - (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#endif - -/* - * Commands for ioctlsocket(), taken from the BSD file fcntl.h. - * - * - * Ioctl's have the command encoded in the lower word, - * and the size of any in or out parameters in the upper - * word. The high 2 bits of the upper word are used - * to encode the in/out status of the parameter; for now - * we restrict parameters to at most 128 bytes. - */ -#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ -#define IOC_VOID 0x20000000 /* no parameters */ -#define IOC_OUT 0x40000000 /* copy out parameters */ -#define IOC_IN 0x80000000 /* copy in parameters */ -#define IOC_INOUT (IOC_IN|IOC_OUT) - /* 0x20000000 distinguishes new & - old ioctl's */ -#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) - -#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) - -#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) - -#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to read */ -#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */ -#define FIOASYNC _IOW('f', 125, u_long) /* set/clear async i/o */ - -/* Socket I/O Controls */ -#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high watermark */ -#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high watermark */ -#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low watermark */ -#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */ -#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark? */ - -/* - * Structures returned by network data base library, taken from the - * BSD file netdb.h. All addresses are supplied in host order, and - * returned in network order (suitable for use in system calls). - */ - -struct hostent { - char FAR * h_name; /* official name of host */ - char FAR * FAR * h_aliases; /* alias list */ - short h_addrtype; /* host address type */ - short h_length; /* length of address */ - char FAR * FAR * h_addr_list; /* list of addresses */ -#define h_addr h_addr_list[0] /* address, for backward compat */ -}; - -/* - * It is assumed here that a network number - * fits in 32 bits. - */ -struct netent { - char FAR * n_name; /* official name of net */ - char FAR * FAR * n_aliases; /* alias list */ - short n_addrtype; /* net address type */ - u_long n_net; /* network # */ -}; - -struct servent { - char FAR * s_name; /* official service name */ - char FAR * FAR * s_aliases; /* alias list */ - short s_port; /* port # */ - char FAR * s_proto; /* protocol to use */ -}; - -struct protoent { - char FAR * p_name; /* official protocol name */ - char FAR * FAR * p_aliases; /* alias list */ - short p_proto; /* protocol # */ -}; - -/* - * Constants and structures defined by the internet system, - * Per RFC 790, September 1981, taken from the BSD file netinet/in.h. - */ - -/* - * Protocols - */ -#define IPPROTO_IP 0 /* dummy for IP */ -#define IPPROTO_ICMP 1 /* control message protocol */ -#define IPPROTO_GGP 2 /* gateway^2 (deprecated) */ -#define IPPROTO_TCP 6 /* tcp */ -#define IPPROTO_PUP 12 /* pup */ -#define IPPROTO_UDP 17 /* user datagram protocol */ -#define IPPROTO_IDP 22 /* xns idp */ -#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */ - -#define IPPROTO_RAW 255 /* raw IP packet */ -#define IPPROTO_MAX 256 - -/* - * Port/socket numbers: network standard functions - */ -#define IPPORT_ECHO 7 -#define IPPORT_DISCARD 9 -#define IPPORT_SYSTAT 11 -#define IPPORT_DAYTIME 13 -#define IPPORT_NETSTAT 15 -#define IPPORT_FTP 21 -#define IPPORT_TELNET 23 -#define IPPORT_SMTP 25 -#define IPPORT_TIMESERVER 37 -#define IPPORT_NAMESERVER 42 -#define IPPORT_WHOIS 43 -#define IPPORT_MTP 57 - -/* - * Port/socket numbers: host specific functions - */ -#define IPPORT_TFTP 69 -#define IPPORT_RJE 77 -#define IPPORT_FINGER 79 -#define IPPORT_TTYLINK 87 -#define IPPORT_SUPDUP 95 - -/* - * UNIX TCP sockets - */ -#define IPPORT_EXECSERVER 512 -#define IPPORT_LOGINSERVER 513 -#define IPPORT_CMDSERVER 514 -#define IPPORT_EFSSERVER 520 - -/* - * UNIX UDP sockets - */ -#define IPPORT_BIFFUDP 512 -#define IPPORT_WHOSERVER 513 -#define IPPORT_ROUTESERVER 520 - /* 520+1 also used */ - -/* - * Ports < IPPORT_RESERVED are reserved for - * privileged processes (e.g. root). - */ -#define IPPORT_RESERVED 1024 - -/* - * Link numbers - */ -#define IMPLINK_IP 155 -#define IMPLINK_LOWEXPER 156 -#define IMPLINK_HIGHEXPER 158 - -/* - * Internet address (old style... should be updated) - */ -struct in_addr { - union { - struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { u_short s_w1,s_w2; } S_un_w; - u_long S_addr; - } S_un; -#define s_addr S_un.S_addr - /* can be used for most tcp & ip code */ -#define s_host S_un.S_un_b.s_b2 - /* host on imp */ -#define s_net S_un.S_un_b.s_b1 - /* network */ -#define s_imp S_un.S_un_w.s_w2 - /* imp */ -#define s_impno S_un.S_un_b.s_b4 - /* imp # */ -#define s_lh S_un.S_un_b.s_b3 - /* logical host */ -}; - -/* - * Definitions of bits in internet address integers. - * On subnets, the decomposition of addresses to host and net parts - * is done according to subnet mask, not the masks here. - */ -#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) -#define IN_CLASSA_NET 0xff000000 -#define IN_CLASSA_NSHIFT 24 -#define IN_CLASSA_HOST 0x00ffffff -#define IN_CLASSA_MAX 128 - -#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) -#define IN_CLASSB_NET 0xffff0000 -#define IN_CLASSB_NSHIFT 16 -#define IN_CLASSB_HOST 0x0000ffff -#define IN_CLASSB_MAX 65536 - -#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) -#define IN_CLASSC_NET 0xffffff00 -#define IN_CLASSC_NSHIFT 8 -#define IN_CLASSC_HOST 0x000000ff - -#define INADDR_ANY (u_long)0x00000000 -#define INADDR_LOOPBACK 0x7f000001 -#define INADDR_BROADCAST (u_long)0xffffffff -#define INADDR_NONE 0xffffffff - -/* - * Socket address, internet style. - */ -struct sockaddr_in { - short sin_family; - u_short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; - -#define WSADESCRIPTION_LEN 256 -#define WSASYS_STATUS_LEN 128 - - -/* - * Options for use with [gs]etsockopt at the IP level. - */ -#define IP_OPTIONS 1 /* set/get IP per-packet options */ -#define IP_MULTICAST_IF 2 /* set/get IP multicast interface */ -#define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */ -#define IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */ -#define IP_ADD_MEMBERSHIP 5 /* add an IP group membership */ -#define IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */ - -#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ -#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ -#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */ - -/* - * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. - */ -struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -}; - -/* - * Definitions related to sockets: types, address families, options, - * taken from the BSD file sys/socket.h. - */ - -/* - * This is used instead of -1, since the - * SOCKET type is unsigned. - */ -#define INVALID_SOCKET (SOCKET)(~0) -#define SOCKET_ERROR (-1) - -/* - * Types - */ -#define SOCK_STREAM 1 /* stream socket */ -#define SOCK_DGRAM 2 /* datagram socket */ -#define SOCK_RAW 3 /* raw-protocol interface */ -#define SOCK_RDM 4 /* reliably-delivered message */ -#define SOCK_SEQPACKET 5 /* sequenced packet stream */ - -/* - * Option flags per-socket. - */ -#define SO_DEBUG 0x0001 /* turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_REUSEADDR 0x0004 /* allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_DONTROUTE 0x0010 /* just use interface addresses */ -#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ -#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ - -#define SO_DONTLINGER (u_int)(~SO_LINGER) - -/* - * Additional options. - */ -#define SO_SNDBUF 0x1001 /* send buffer size */ -#define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ -#define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ERROR 0x1007 /* get error status and clear */ -#define SO_TYPE 0x1008 /* get socket type */ - -/* - * Options for connect and disconnect data and options. Used only by - * non-TCP/IP transports such as DECNet, OSI TP4, etc. - */ -#define SO_CONNDATA 0x7000 -#define SO_CONNOPT 0x7001 -#define SO_DISCDATA 0x7002 -#define SO_DISCOPT 0x7003 -#define SO_CONNDATALEN 0x7004 -#define SO_CONNOPTLEN 0x7005 -#define SO_DISCDATALEN 0x7006 -#define SO_DISCOPTLEN 0x7007 - -/* - * Option for opening sockets for synchronous access. - */ -#define SO_OPENTYPE 0x7008 - -#define SO_SYNCHRONOUS_ALERT 0x10 -#define SO_SYNCHRONOUS_NONALERT 0x20 - -/* - * Other NT-specific options. - */ -#define SO_MAXDG 0x7009 -#define SO_MAXPATHDG 0x700A - -/* - * TCP options. - */ -#define TCP_NODELAY 0x0001 -#define TCP_BSDURGENT 0x7000 - -/* - * Address families. - */ -#define AF_UNSPEC 0 /* unspecified */ -#define AF_UNIX 1 /* local to host (pipes, portals) */ -#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ -#define AF_IMPLINK 3 /* arpanet imp addresses */ -#define AF_PUP 4 /* pup protocols: e.g. BSP */ -#define AF_CHAOS 5 /* mit CHAOS protocols */ -#define AF_IPX 6 /* IPX and SPX */ -#define AF_NS 6 /* XEROX NS protocols */ -#define AF_ISO 7 /* ISO protocols */ -#define AF_OSI AF_ISO /* OSI is ISO */ -#define AF_ECMA 8 /* european computer manufacturers */ -#define AF_DATAKIT 9 /* datakit protocols */ -#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ -#define AF_SNA 11 /* IBM SNA */ -#define AF_DECnet 12 /* DECnet */ -#define AF_DLI 13 /* Direct data link interface */ -#define AF_LAT 14 /* LAT */ -#define AF_HYLINK 15 /* NSC Hyperchannel */ -#define AF_APPLETALK 16 /* AppleTalk */ -#define AF_NETBIOS 17 /* NetBios-style addresses */ -#define AF_VOICEVIEW 18 /* VoiceView */ - -#define AF_MAX 19 - -/* - * Structure used by kernel to store most - * addresses. - */ -struct sockaddr { - u_short sa_family; /* address family */ - char sa_data[14]; /* up to 14 bytes of direct address */ -}; - -/* - * Structure used by kernel to pass protocol - * information in raw sockets. - */ -struct sockproto { - u_short sp_family; /* address family */ - u_short sp_protocol; /* protocol */ -}; - -/* - * Protocol families, same as address families for now. - */ -#define PF_UNSPEC AF_UNSPEC -#define PF_UNIX AF_UNIX -#define PF_INET AF_INET -#define PF_IMPLINK AF_IMPLINK -#define PF_PUP AF_PUP -#define PF_CHAOS AF_CHAOS -#define PF_NS AF_NS -#define PF_IPX AF_IPX -#define PF_ISO AF_ISO -#define PF_OSI AF_OSI -#define PF_ECMA AF_ECMA -#define PF_DATAKIT AF_DATAKIT -#define PF_CCITT AF_CCITT -#define PF_SNA AF_SNA -#define PF_DECnet AF_DECnet -#define PF_DLI AF_DLI -#define PF_LAT AF_LAT -#define PF_HYLINK AF_HYLINK -#define PF_APPLETALK AF_APPLETALK -#define PF_VOICEVIEW AF_VOICEVIEW - -#define PF_MAX AF_MAX - -/* - * Structure used for manipulating linger option. - */ -struct linger { - u_short l_onoff; /* option on/off */ - u_short l_linger; /* linger time */ -}; - -/* - * Level number for (get/set)sockopt() to apply to socket itself. - */ -#define SOL_SOCKET 0xffff /* options for socket level */ - -/* - * Maximum queue length specifiable by listen. - */ -#define SOMAXCONN 5 - -#define MSG_OOB 0x1 /* process out-of-band data */ -#define MSG_PEEK 0x2 /* peek at incoming message */ -#define MSG_DONTROUTE 0x4 /* send without using routing tables */ - -#define MSG_MAXIOVLEN 16 - -#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */ - -/* - * Define constant based on rfc883, used by gethostbyxxxx() calls. - */ -#define MAXGETHOSTSTRUCT 1024 - -/* - * Define flags to be used with the WSAAsyncSelect() call. - */ -#define FD_READ 0x01 -#define FD_WRITE 0x02 -#define FD_OOB 0x04 -#define FD_ACCEPT 0x08 -#define FD_CONNECT 0x10 -#define FD_CLOSE 0x20 - -/* - * All Windows Sockets error constants are biased by WSABASEERR from - * the "normal" - */ -#define WSABASEERR 10000 -/* - * Windows Sockets definitions of regular Microsoft C error constants - */ -#define WSAEINTR (WSABASEERR+4) -#define WSAEBADF (WSABASEERR+9) -#define WSAEACCES (WSABASEERR+13) -#define WSAEFAULT (WSABASEERR+14) -#define WSAEINVAL (WSABASEERR+22) -#define WSAEMFILE (WSABASEERR+24) - -/* - * Windows Sockets definitions of regular Berkeley error constants - */ -#define WSAEWOULDBLOCK (WSABASEERR+35) -#define WSAEINPROGRESS (WSABASEERR+36) -#define WSAEALREADY (WSABASEERR+37) -#define WSAENOTSOCK (WSABASEERR+38) -#define WSAEDESTADDRREQ (WSABASEERR+39) -#define WSAEMSGSIZE (WSABASEERR+40) -#define WSAEPROTOTYPE (WSABASEERR+41) -#define WSAENOPROTOOPT (WSABASEERR+42) -#define WSAEPROTONOSUPPORT (WSABASEERR+43) -#define WSAESOCKTNOSUPPORT (WSABASEERR+44) -#define WSAEOPNOTSUPP (WSABASEERR+45) -#define WSAEPFNOSUPPORT (WSABASEERR+46) -#define WSAEAFNOSUPPORT (WSABASEERR+47) -#define WSAEADDRINUSE (WSABASEERR+48) -#define WSAEADDRNOTAVAIL (WSABASEERR+49) -#define WSAENETDOWN (WSABASEERR+50) -#define WSAENETUNREACH (WSABASEERR+51) -#define WSAENETRESET (WSABASEERR+52) -#define WSAECONNABORTED (WSABASEERR+53) -#define WSAECONNRESET (WSABASEERR+54) -#define WSAENOBUFS (WSABASEERR+55) -#define WSAEISCONN (WSABASEERR+56) -#define WSAENOTCONN (WSABASEERR+57) -#define WSAESHUTDOWN (WSABASEERR+58) -#define WSAETOOMANYREFS (WSABASEERR+59) -#define WSAETIMEDOUT (WSABASEERR+60) -#define WSAECONNREFUSED (WSABASEERR+61) -#define WSAELOOP (WSABASEERR+62) -#define WSAENAMETOOLONG (WSABASEERR+63) -#define WSAEHOSTDOWN (WSABASEERR+64) -#define WSAEHOSTUNREACH (WSABASEERR+65) -#define WSAENOTEMPTY (WSABASEERR+66) -#define WSAEPROCLIM (WSABASEERR+67) -#define WSAEUSERS (WSABASEERR+68) -#define WSAEDQUOT (WSABASEERR+69) -#define WSAESTALE (WSABASEERR+70) -#define WSAEREMOTE (WSABASEERR+71) - -#define WSAEDISCON (WSABASEERR+101) - -/* - * Extended Windows Sockets error constant definitions - */ -#define WSASYSNOTREADY (WSABASEERR+91) -#define WSAVERNOTSUPPORTED (WSABASEERR+92) -#define WSANOTINITIALISED (WSABASEERR+93) - -/* - * Error return codes from gethostbyname() and gethostbyaddr() - * (when using the resolver). Note that these errors are - * retrieved via WSAGetLastError() and must therefore follow - * the rules for avoiding clashes with error numbers from - * specific implementations or language run-time systems. - * For this reason the codes are based at WSABASEERR+1001. - * Note also that [WSA]NO_ADDRESS is defined only for - * compatibility purposes. - */ - -#define h_errno WSAGetLastError() - -/* Authoritative Answer: Host not found */ -#define WSAHOST_NOT_FOUND (WSABASEERR+1001) -#define HOST_NOT_FOUND WSAHOST_NOT_FOUND - -/* Non-Authoritative: Host not found, or SERVERFAIL */ -#define WSATRY_AGAIN (WSABASEERR+1002) -#define TRY_AGAIN WSATRY_AGAIN - -/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ -#define WSANO_RECOVERY (WSABASEERR+1003) -#define NO_RECOVERY WSANO_RECOVERY - -/* Valid name, no data record of requested type */ -#define WSANO_DATA (WSABASEERR+1004) -#define NO_DATA WSANO_DATA - -/* no address, look for MX record */ -#define WSANO_ADDRESS WSANO_DATA -#define NO_ADDRESS WSANO_ADDRESS - -/* - * Windows Sockets errors redefined as regular Berkeley error constants. - * These are commented out in Windows NT to avoid conflicts with errno.h. - * Use the WSA constants instead. - */ -#if 0 -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EINPROGRESS WSAEINPROGRESS -#define EALREADY WSAEALREADY -#define ENOTSOCK WSAENOTSOCK -#define EDESTADDRREQ WSAEDESTADDRREQ -#define EMSGSIZE WSAEMSGSIZE -#define EPROTOTYPE WSAEPROTOTYPE -#define ENOPROTOOPT WSAENOPROTOOPT -#define EPROTONOSUPPORT WSAEPROTONOSUPPORT -#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT -#define EOPNOTSUPP WSAEOPNOTSUPP -#define EPFNOSUPPORT WSAEPFNOSUPPORT -#define EAFNOSUPPORT WSAEAFNOSUPPORT -#define EADDRINUSE WSAEADDRINUSE -#define EADDRNOTAVAIL WSAEADDRNOTAVAIL -#define ENETDOWN WSAENETDOWN -#define ENETUNREACH WSAENETUNREACH -#define ENETRESET WSAENETRESET -#define ECONNABORTED WSAECONNABORTED -#define ECONNRESET WSAECONNRESET -#define ENOBUFS WSAENOBUFS -#define EISCONN WSAEISCONN -#define ENOTCONN WSAENOTCONN -#define ESHUTDOWN WSAESHUTDOWN -#define ETOOMANYREFS WSAETOOMANYREFS -#define ETIMEDOUT WSAETIMEDOUT -#define ECONNREFUSED WSAECONNREFUSED -#define ELOOP WSAELOOP -#define ENAMETOOLONG WSAENAMETOOLONG -#define EHOSTDOWN WSAEHOSTDOWN -#define EHOSTUNREACH WSAEHOSTUNREACH -#define ENOTEMPTY WSAENOTEMPTY -#define EPROCLIM WSAEPROCLIM -#define EUSERS WSAEUSERS -#define EDQUOT WSAEDQUOT -#define ESTALE WSAESTALE -#define EREMOTE WSAEREMOTE -#endif - -/* Socket function prototypes */ - -#ifdef __cplusplus -extern "C" { -#endif - -SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr, - int FAR *addrlen); - -int PASCAL FAR bind (SOCKET s, const struct sockaddr FAR *addr, int namelen); - -int PASCAL FAR closesocket (SOCKET s); - -int PASCAL FAR connect (SOCKET s, const struct sockaddr FAR *name, int namelen); - -int PASCAL FAR ioctlsocket (SOCKET s, long cmd, u_long FAR *argp); - -int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name, - int FAR * namelen); - -int PASCAL FAR getsockname (SOCKET s, struct sockaddr FAR *name, - int FAR * namelen); - -int PASCAL FAR getsockopt (SOCKET s, int level, int optname, - char FAR * optval, int FAR *optlen); - -u_long PASCAL FAR htonl (u_long hostlong); - -u_short PASCAL FAR htons (u_short hostshort); - -unsigned long PASCAL FAR inet_addr (const char FAR * cp); - -char FAR * PASCAL FAR inet_ntoa (struct in_addr in); - -int PASCAL FAR listen (SOCKET s, int backlog); - -u_long PASCAL FAR ntohl (u_long netlong); - -u_short PASCAL FAR ntohs (u_short netshort); - -int PASCAL FAR recv (SOCKET s, char FAR * buf, int len, int flags); - -int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags, - struct sockaddr FAR *from, int FAR * fromlen); - -#if 0 -int PASCAL FAR select (int nfds, fd_set FAR *readfds, fd_set FAR *writefds, - fd_set FAR *exceptfds, const struct timeval FAR *timeout); -#endif - -int PASCAL FAR send (SOCKET s, const char FAR * buf, int len, int flags); - -int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags, - const struct sockaddr FAR *to, int tolen); - -int PASCAL FAR setsockopt (SOCKET s, int level, int optname, - const char FAR * optval, int optlen); - -int PASCAL FAR shutdown (SOCKET s, int how); - -SOCKET PASCAL FAR socket (int af, int type, int protocol); - -/* Database function prototypes */ - -struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr, - int len, int type); - -struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name); - -int PASCAL FAR gethostname (char FAR * name, int namelen); - -struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto); - -struct servent FAR * PASCAL FAR getservbyname(const char FAR * name, - const char FAR * proto); - -struct protoent FAR * PASCAL FAR getprotobynumber(int proto); - -struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name); - -#ifdef __cplusplus -} -#endif - -/* Microsoft Windows Extended data types */ -typedef struct sockaddr SOCKADDR; -typedef struct sockaddr *PSOCKADDR; -typedef struct sockaddr FAR *LPSOCKADDR; - -typedef struct sockaddr_in SOCKADDR_IN; -typedef struct sockaddr_in *PSOCKADDR_IN; -typedef struct sockaddr_in FAR *LPSOCKADDR_IN; - -typedef struct linger LINGER; -typedef struct linger *PLINGER; -typedef struct linger FAR *LPLINGER; - -typedef struct in_addr IN_ADDR; -typedef struct in_addr *PIN_ADDR; -typedef struct in_addr FAR *LPIN_ADDR; - -typedef struct fd_set FD_SET; -typedef struct fd_set *PFD_SET; -typedef struct fd_set FAR *LPFD_SET; - -typedef struct hostent HOSTENT; -typedef struct hostent *PHOSTENT; -typedef struct hostent FAR *LPHOSTENT; - -typedef struct servent SERVENT; -typedef struct servent *PSERVENT; -typedef struct servent FAR *LPSERVENT; - -typedef struct protoent PROTOENT; -typedef struct protoent *PPROTOENT; -typedef struct protoent FAR *LPPROTOENT; - -typedef struct timeval TIMEVAL; -typedef struct timeval *PTIMEVAL; -typedef struct timeval FAR *LPTIMEVAL; - -#endif /* _WINSOCKAPI_ */ +/* WINSOCK.H--definitions to be used with the WINSOCK.DLL + * Copyright (c) 1993-1995, Microsoft Corp. All rights reserved. + * + * This header file corresponds to version 1.1 of the Windows Sockets specification. + * + * This file includes parts which are Copyright (c) 1982-1986 Regents + * of the University of California. All rights reserved. The + * Berkeley Software License Agreement specifies the terms and + * conditions for redistribution. + * + */ + +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ + +#define FAR +#define PASCAL + +/* + * Basic system type definitions, taken from the BSD file sys/types.h. + */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +/* + * The new type to be used in all + * instances which refer to sockets. + */ +typedef u_int SOCKET; + +// FIXME +#if 0 +/* + * Select uses arrays of SOCKETs. These macros manipulate such + * arrays. FD_SETSIZE may be defined by the user before including + * this file, but the default here should be >= 64. + * + * CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE + * INCLUDED IN WINSOCK.H EXACTLY AS SHOWN HERE. + */ +#ifndef FD_SETSIZE +#define FD_SETSIZE 64 +#endif /* FD_SETSIZE */ + +typedef struct fd_set { + u_int fd_count; /* how many are SET? */ + SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */ +} fd_set; + +#ifdef __cplusplus +extern "C" { +#endif + +extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *); + +#ifdef __cplusplus +} +#endif + + +#define FD_CLR(fd, set) do { \ + u_int __i; \ + for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \ + if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \ + while (__i < ((fd_set FAR *)(set))->fd_count-1) { \ + ((fd_set FAR *)(set))->fd_array[__i] = \ + ((fd_set FAR *)(set))->fd_array[__i+1]; \ + __i++; \ + } \ + ((fd_set FAR *)(set))->fd_count--; \ + break; \ + } \ + } \ +} while(0) + +#define FD_SET(fd, set) do { \ + if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \ + ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ +} while(0) + +#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0) + +#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set)) + +/* + * Structure used in select() call, taken from the BSD file sys/time.h. + */ +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +/* + * Operations on timevals. + * + * NB: timercmp does not work for >= or <=. + */ +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + ((tvp)->tv_sec cmp (uvp)->tv_sec || \ + (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000 /* no parameters */ +#define IOC_OUT 0x40000000 /* copy out parameters */ +#define IOC_IN 0x80000000 /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to read */ +#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */ +#define FIOASYNC _IOW('f', 125, u_long) /* set/clear async i/o */ + +/* Socket I/O Controls */ +#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark? */ + +/* + * Structures returned by network data base library, taken from the + * BSD file netdb.h. All addresses are supplied in host order, and + * returned in network order (suitable for use in system calls). + */ + +struct hostent { + char FAR * h_name; /* official name of host */ + char FAR * FAR * h_aliases; /* alias list */ + short h_addrtype; /* host address type */ + short h_length; /* length of address */ + char FAR * FAR * h_addr_list; /* list of addresses */ +#define h_addr h_addr_list[0] /* address, for backward compat */ +}; + +/* + * It is assumed here that a network number + * fits in 32 bits. + */ +struct netent { + char FAR * n_name; /* official name of net */ + char FAR * FAR * n_aliases; /* alias list */ + short n_addrtype; /* net address type */ + u_long n_net; /* network # */ +}; + +struct servent { + char FAR * s_name; /* official service name */ + char FAR * FAR * s_aliases; /* alias list */ + short s_port; /* port # */ + char FAR * s_proto; /* protocol to use */ +}; + +struct protoent { + char FAR * p_name; /* official protocol name */ + char FAR * FAR * p_aliases; /* alias list */ + short p_proto; /* protocol # */ +}; + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, taken from the BSD file netinet/in.h. + */ + +/* + * Protocols + */ +#define IPPROTO_IP 0 /* dummy for IP */ +#define IPPROTO_ICMP 1 /* control message protocol */ +#define IPPROTO_GGP 2 /* gateway^2 (deprecated) */ +#define IPPROTO_TCP 6 /* tcp */ +#define IPPROTO_PUP 12 /* pup */ +#define IPPROTO_UDP 17 /* user datagram protocol */ +#define IPPROTO_IDP 22 /* xns idp */ +#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */ + +#define IPPROTO_RAW 255 /* raw IP packet */ +#define IPPROTO_MAX 256 + +/* + * Port/socket numbers: network standard functions + */ +#define IPPORT_ECHO 7 +#define IPPORT_DISCARD 9 +#define IPPORT_SYSTAT 11 +#define IPPORT_DAYTIME 13 +#define IPPORT_NETSTAT 15 +#define IPPORT_FTP 21 +#define IPPORT_TELNET 23 +#define IPPORT_SMTP 25 +#define IPPORT_TIMESERVER 37 +#define IPPORT_NAMESERVER 42 +#define IPPORT_WHOIS 43 +#define IPPORT_MTP 57 + +/* + * Port/socket numbers: host specific functions + */ +#define IPPORT_TFTP 69 +#define IPPORT_RJE 77 +#define IPPORT_FINGER 79 +#define IPPORT_TTYLINK 87 +#define IPPORT_SUPDUP 95 + +/* + * UNIX TCP sockets + */ +#define IPPORT_EXECSERVER 512 +#define IPPORT_LOGINSERVER 513 +#define IPPORT_CMDSERVER 514 +#define IPPORT_EFSSERVER 520 + +/* + * UNIX UDP sockets + */ +#define IPPORT_BIFFUDP 512 +#define IPPORT_WHOSERVER 513 +#define IPPORT_ROUTESERVER 520 + /* 520+1 also used */ + +/* + * Ports < IPPORT_RESERVED are reserved for + * privileged processes (e.g. root). + */ +#define IPPORT_RESERVED 1024 + +/* + * Link numbers + */ +#define IMPLINK_IP 155 +#define IMPLINK_LOWEXPER 156 +#define IMPLINK_HIGHEXPER 158 + +/* + * Internet address (old style... should be updated) + */ +struct in_addr { + union { + struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { u_short s_w1,s_w2; } S_un_w; + u_long S_addr; + } S_un; +#define s_addr S_un.S_addr + /* can be used for most tcp & ip code */ +#define s_host S_un.S_un_b.s_b2 + /* host on imp */ +#define s_net S_un.S_un_b.s_b1 + /* network */ +#define s_imp S_un.S_un_w.s_w2 + /* imp */ +#define s_impno S_un.S_un_b.s_b4 + /* imp # */ +#define s_lh S_un.S_un_b.s_b3 + /* logical host */ +}; + +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define INADDR_ANY (u_long)0x00000000 +#define INADDR_LOOPBACK 0x7f000001 +#define INADDR_BROADCAST (u_long)0xffffffff +#define INADDR_NONE 0xffffffff + +/* + * Socket address, internet style. + */ +struct sockaddr_in { + short sin_family; + u_short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +#define WSADESCRIPTION_LEN 256 +#define WSASYS_STATUS_LEN 128 + + +/* + * Options for use with [gs]etsockopt at the IP level. + */ +#define IP_OPTIONS 1 /* set/get IP per-packet options */ +#define IP_MULTICAST_IF 2 /* set/get IP multicast interface */ +#define IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */ +#define IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 5 /* add an IP group membership */ +#define IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */ + +#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ +#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ +#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */ + +/* + * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. + */ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +/* + * Definitions related to sockets: types, address families, options, + * taken from the BSD file sys/socket.h. + */ + +/* + * This is used instead of -1, since the + * SOCKET type is unsigned. + */ +#define INVALID_SOCKET (SOCKET)(~0) +#define SOCKET_ERROR (-1) + +/* + * Types + */ +#define SOCK_STREAM 1 /* stream socket */ +#define SOCK_DGRAM 2 /* datagram socket */ +#define SOCK_RAW 3 /* raw-protocol interface */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequenced packet stream */ + +/* + * Option flags per-socket. + */ +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ + +#define SO_DONTLINGER (u_int)(~SO_LINGER) + +/* + * Additional options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ + +/* + * Options for connect and disconnect data and options. Used only by + * non-TCP/IP transports such as DECNet, OSI TP4, etc. + */ +#define SO_CONNDATA 0x7000 +#define SO_CONNOPT 0x7001 +#define SO_DISCDATA 0x7002 +#define SO_DISCOPT 0x7003 +#define SO_CONNDATALEN 0x7004 +#define SO_CONNOPTLEN 0x7005 +#define SO_DISCDATALEN 0x7006 +#define SO_DISCOPTLEN 0x7007 + +/* + * Option for opening sockets for synchronous access. + */ +#define SO_OPENTYPE 0x7008 + +#define SO_SYNCHRONOUS_ALERT 0x10 +#define SO_SYNCHRONOUS_NONALERT 0x20 + +/* + * Other NT-specific options. + */ +#define SO_MAXDG 0x7009 +#define SO_MAXPATHDG 0x700A + +/* + * TCP options. + */ +#define TCP_NODELAY 0x0001 +#define TCP_BSDURGENT 0x7000 + +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_UNIX 1 /* local to host (pipes, portals) */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_IPX 6 /* IPX and SPX */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO /* OSI is ISO */ +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* AppleTalk */ +#define AF_NETBIOS 17 /* NetBios-style addresses */ +#define AF_VOICEVIEW 18 /* VoiceView */ + +#define AF_MAX 19 + +/* + * Structure used by kernel to store most + * addresses. + */ +struct sockaddr { + u_short sa_family; /* address family */ + char sa_data[14]; /* up to 14 bytes of direct address */ +}; + +/* + * Structure used by kernel to pass protocol + * information in raw sockets. + */ +struct sockproto { + u_short sp_family; /* address family */ + u_short sp_protocol; /* protocol */ +}; + +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_IPX AF_IPX +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_VOICEVIEW AF_VOICEVIEW + +#define PF_MAX AF_MAX + +/* + * Structure used for manipulating linger option. + */ +struct linger { + u_short l_onoff; /* option on/off */ + u_short l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Maximum queue length specifiable by listen. + */ +#define SOMAXCONN 5 + +#define MSG_OOB 0x1 /* process out-of-band data */ +#define MSG_PEEK 0x2 /* peek at incoming message */ +#define MSG_DONTROUTE 0x4 /* send without using routing tables */ + +#define MSG_MAXIOVLEN 16 + +#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */ + +/* + * Define constant based on rfc883, used by gethostbyxxxx() calls. + */ +#define MAXGETHOSTSTRUCT 1024 + +/* + * Define flags to be used with the WSAAsyncSelect() call. + */ +#define FD_READ 0x01 +#define FD_WRITE 0x02 +#define FD_OOB 0x04 +#define FD_ACCEPT 0x08 +#define FD_CONNECT 0x10 +#define FD_CLOSE 0x20 + +/* + * All Windows Sockets error constants are biased by WSABASEERR from + * the "normal" + */ +#define WSABASEERR 10000 +/* + * Windows Sockets definitions of regular Microsoft C error constants + */ +#define WSAEINTR (WSABASEERR+4) +#define WSAEBADF (WSABASEERR+9) +#define WSAEACCES (WSABASEERR+13) +#define WSAEFAULT (WSABASEERR+14) +#define WSAEINVAL (WSABASEERR+22) +#define WSAEMFILE (WSABASEERR+24) + +/* + * Windows Sockets definitions of regular Berkeley error constants + */ +#define WSAEWOULDBLOCK (WSABASEERR+35) +#define WSAEINPROGRESS (WSABASEERR+36) +#define WSAEALREADY (WSABASEERR+37) +#define WSAENOTSOCK (WSABASEERR+38) +#define WSAEDESTADDRREQ (WSABASEERR+39) +#define WSAEMSGSIZE (WSABASEERR+40) +#define WSAEPROTOTYPE (WSABASEERR+41) +#define WSAENOPROTOOPT (WSABASEERR+42) +#define WSAEPROTONOSUPPORT (WSABASEERR+43) +#define WSAESOCKTNOSUPPORT (WSABASEERR+44) +#define WSAEOPNOTSUPP (WSABASEERR+45) +#define WSAEPFNOSUPPORT (WSABASEERR+46) +#define WSAEAFNOSUPPORT (WSABASEERR+47) +#define WSAEADDRINUSE (WSABASEERR+48) +#define WSAEADDRNOTAVAIL (WSABASEERR+49) +#define WSAENETDOWN (WSABASEERR+50) +#define WSAENETUNREACH (WSABASEERR+51) +#define WSAENETRESET (WSABASEERR+52) +#define WSAECONNABORTED (WSABASEERR+53) +#define WSAECONNRESET (WSABASEERR+54) +#define WSAENOBUFS (WSABASEERR+55) +#define WSAEISCONN (WSABASEERR+56) +#define WSAENOTCONN (WSABASEERR+57) +#define WSAESHUTDOWN (WSABASEERR+58) +#define WSAETOOMANYREFS (WSABASEERR+59) +#define WSAETIMEDOUT (WSABASEERR+60) +#define WSAECONNREFUSED (WSABASEERR+61) +#define WSAELOOP (WSABASEERR+62) +#define WSAENAMETOOLONG (WSABASEERR+63) +#define WSAEHOSTDOWN (WSABASEERR+64) +#define WSAEHOSTUNREACH (WSABASEERR+65) +#define WSAENOTEMPTY (WSABASEERR+66) +#define WSAEPROCLIM (WSABASEERR+67) +#define WSAEUSERS (WSABASEERR+68) +#define WSAEDQUOT (WSABASEERR+69) +#define WSAESTALE (WSABASEERR+70) +#define WSAEREMOTE (WSABASEERR+71) + +#define WSAEDISCON (WSABASEERR+101) + +/* + * Extended Windows Sockets error constant definitions + */ +#define WSASYSNOTREADY (WSABASEERR+91) +#define WSAVERNOTSUPPORTED (WSABASEERR+92) +#define WSANOTINITIALISED (WSABASEERR+93) + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (when using the resolver). Note that these errors are + * retrieved via WSAGetLastError() and must therefore follow + * the rules for avoiding clashes with error numbers from + * specific implementations or language run-time systems. + * For this reason the codes are based at WSABASEERR+1001. + * Note also that [WSA]NO_ADDRESS is defined only for + * compatibility purposes. + */ + +#define h_errno WSAGetLastError() + +/* Authoritative Answer: Host not found */ +#define WSAHOST_NOT_FOUND (WSABASEERR+1001) +#define HOST_NOT_FOUND WSAHOST_NOT_FOUND + +/* Non-Authoritative: Host not found, or SERVERFAIL */ +#define WSATRY_AGAIN (WSABASEERR+1002) +#define TRY_AGAIN WSATRY_AGAIN + +/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define WSANO_RECOVERY (WSABASEERR+1003) +#define NO_RECOVERY WSANO_RECOVERY + +/* Valid name, no data record of requested type */ +#define WSANO_DATA (WSABASEERR+1004) +#define NO_DATA WSANO_DATA + +/* no address, look for MX record */ +#define WSANO_ADDRESS WSANO_DATA +#define NO_ADDRESS WSANO_ADDRESS + +/* + * Windows Sockets errors redefined as regular Berkeley error constants. + * These are commented out in Windows NT to avoid conflicts with errno.h. + * Use the WSA constants instead. + */ +#if 0 +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EINPROGRESS WSAEINPROGRESS +#define EALREADY WSAEALREADY +#define ENOTSOCK WSAENOTSOCK +#define EDESTADDRREQ WSAEDESTADDRREQ +#define EMSGSIZE WSAEMSGSIZE +#define EPROTOTYPE WSAEPROTOTYPE +#define ENOPROTOOPT WSAENOPROTOOPT +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define EADDRINUSE WSAEADDRINUSE +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#define ENETDOWN WSAENETDOWN +#define ENETUNREACH WSAENETUNREACH +#define ENETRESET WSAENETRESET +#define ECONNABORTED WSAECONNABORTED +#define ECONNRESET WSAECONNRESET +#define ENOBUFS WSAENOBUFS +#define EISCONN WSAEISCONN +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#define ETIMEDOUT WSAETIMEDOUT +#define ECONNREFUSED WSAECONNREFUSED +#define ELOOP WSAELOOP +#define ENAMETOOLONG WSAENAMETOOLONG +#define EHOSTDOWN WSAEHOSTDOWN +#define EHOSTUNREACH WSAEHOSTUNREACH +#define ENOTEMPTY WSAENOTEMPTY +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* Socket function prototypes */ + +#ifdef __cplusplus +extern "C" { +#endif + +SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr, + int FAR *addrlen); + +int PASCAL FAR bind (SOCKET s, const struct sockaddr FAR *addr, int namelen); + +int PASCAL FAR closesocket (SOCKET s); + +int PASCAL FAR connect (SOCKET s, const struct sockaddr FAR *name, int namelen); + +int PASCAL FAR ioctlsocket (SOCKET s, long cmd, u_long FAR *argp); + +int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name, + int FAR * namelen); + +int PASCAL FAR getsockname (SOCKET s, struct sockaddr FAR *name, + int FAR * namelen); + +int PASCAL FAR getsockopt (SOCKET s, int level, int optname, + char FAR * optval, int FAR *optlen); + +u_long PASCAL FAR htonl (u_long hostlong); + +u_short PASCAL FAR htons (u_short hostshort); + +unsigned long PASCAL FAR inet_addr (const char FAR * cp); + +char FAR * PASCAL FAR inet_ntoa (struct in_addr in); + +int PASCAL FAR listen (SOCKET s, int backlog); + +u_long PASCAL FAR ntohl (u_long netlong); + +u_short PASCAL FAR ntohs (u_short netshort); + +int PASCAL FAR recv (SOCKET s, char FAR * buf, int len, int flags); + +int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags, + struct sockaddr FAR *from, int FAR * fromlen); + +#if 0 +int PASCAL FAR select (int nfds, fd_set FAR *readfds, fd_set FAR *writefds, + fd_set FAR *exceptfds, const struct timeval FAR *timeout); +#endif + +int PASCAL FAR send (SOCKET s, const char FAR * buf, int len, int flags); + +int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags, + const struct sockaddr FAR *to, int tolen); + +int PASCAL FAR setsockopt (SOCKET s, int level, int optname, + const char FAR * optval, int optlen); + +int PASCAL FAR shutdown (SOCKET s, int how); + +SOCKET PASCAL FAR socket (int af, int type, int protocol); + +/* Database function prototypes */ + +struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr, + int len, int type); + +struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name); + +int PASCAL FAR gethostname (char FAR * name, int namelen); + +struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto); + +struct servent FAR * PASCAL FAR getservbyname(const char FAR * name, + const char FAR * proto); + +struct protoent FAR * PASCAL FAR getprotobynumber(int proto); + +struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name); + +#ifdef __cplusplus +} +#endif + +/* Microsoft Windows Extended data types */ +typedef struct sockaddr SOCKADDR; +typedef struct sockaddr *PSOCKADDR; +typedef struct sockaddr FAR *LPSOCKADDR; + +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr_in *PSOCKADDR_IN; +typedef struct sockaddr_in FAR *LPSOCKADDR_IN; + +typedef struct linger LINGER; +typedef struct linger *PLINGER; +typedef struct linger FAR *LPLINGER; + +typedef struct in_addr IN_ADDR; +typedef struct in_addr *PIN_ADDR; +typedef struct in_addr FAR *LPIN_ADDR; + +typedef struct fd_set FD_SET; +typedef struct fd_set *PFD_SET; +typedef struct fd_set FAR *LPFD_SET; + +typedef struct hostent HOSTENT; +typedef struct hostent *PHOSTENT; +typedef struct hostent FAR *LPHOSTENT; + +typedef struct servent SERVENT; +typedef struct servent *PSERVENT; +typedef struct servent FAR *LPSERVENT; + +typedef struct protoent PROTOENT; +typedef struct protoent *PPROTOENT; +typedef struct protoent FAR *LPPROTOENT; + +typedef struct timeval TIMEVAL; +typedef struct timeval *PTIMEVAL; +typedef struct timeval FAR *LPTIMEVAL; + +#endif /* _WINSOCKAPI_ */ diff --git a/WinQuake/mplib.c b/WinQuake/mplib.c index 8ad33ff..6009286 100644 --- a/WinQuake/mplib.c +++ b/WinQuake/mplib.c @@ -1,222 +1,222 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include - -//#include "types.h" -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; - -//#include "mgenord.h" -#define MGENVXD_REGISTER_ORD 1 -#define MGENVXD_GETMEM_ORD 2 -#define MGENVXD_DEREGISTER_ORD 3 -#define MGENVXD_WAKEUP_ORD 4 -#define MGENVXD_MAKEDQS_ORD 5 - - -// Virtual 8086 API Ordinals -#define V86API_GETSELECTOR16_ORD (1) -#define V86API_GETSELECTOR32_ORD (2) -#define V86API_GETFLAT32_ORD (3) -#define V86API_MOVERP_ORD (6) -#define V86API_MOVEPR_ORD (7) -#define V86API_POST_ORD (8) -#define V86API_INIT_ORD (9) -#define V86API_UNINIT_ORD (10) -#define V86API_INSERTKEY_ORD (11) -#define V86API_REMOVEHOTKEY_ORD (12) -#define V86API_INSTALLHOTKEY_ORD (13) -#define V86API_HOOKINT48_ORD (14) -#define V86API_WAKEUPDLL_ORD (15) - -#define DPMIAPI_GETFLAT32_ORD (1) -#define DPMIAPI_POST_WINDOWS_ORD (2) -// these are DPMI functions. Make sure they don't clash with the -// other MGENVXD_XXXX functions above, or the DPMI functions! -#define MGENVXD_GETQUEUECTR_ORD 6 -#define MGENVXD_MOVENODE_ORD 7 -#define MGENVXD_GETNODE_ORD 8 -#define MGENVXD_FLUSHNODE_ORD 9 -#define MGENVXD_MCOUNT_ORD 10 -#define MGENVXD_MASTERNODE_ORD 11 -#define MGENVXD_SANITYCHECK_ORD 12 -#define MGENVXD_WAKEUPDLL_ORD 13 -#define MGENVXD_WAIT_ORD 14 - -// -#define HWND_OFFSET (0) -#define UMSG_OFFSET (1) -#define SIZEREQUEST_OFFSET (2) -#define HVXD_OFFSET (3) -#define DATUM_OFFSET (4) -#define SLOT_OFFSET (5) -#define SIZEGIVEN_OFFSET (6) -#define SELECTOR32_OFFSET (7) -#define SELECTOR16_OFFSET (8) - -//#include "magic.h" -#define MGENVXD_DEVICE_ID 0x18AA - -//#include "rtq.h" -#define RTQ_NODE struct rtq_node - -RTQ_NODE - { - RTQ_NODE *self; // Ring zero address of this node - RTQ_NODE *left; // Ring zero address of preceding node - RTQ_NODE *right; // Ring zero address of succeding node - BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface) - BYTE * rtqInsert; // Ring 3 insertion position - WORD rtqLen; // Length of buffer, excluding preface - WORD rtqUpCtr; // Up Counter of bytes used so far - WORD rtqQCtr; // number of nodes attached - WORD padding; // DWORD alignment - }; - -#define RTQ_PARAM_MOVENODE struct rtq_param_movenode -RTQ_PARAM_MOVENODE - { - WORD rtqFromDQ; - WORD rtqToDQ; - }; - -RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From - -int _int86(int vector, __dpmi_regs *iregs, __dpmi_regs *oregs); - -#define CHUNNEL_INT 0x48 - -#define int386 _int86 -#define REGISTERS __dpmi_regs - -void -Yield(void) -{ - __dpmi_yield(); -} - -void -PostWindowsMessage(void) -{ - REGISTERS regs; - - regs.d.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = 0; - regs.d.ecx = 0; - int386(CHUNNEL_INT, ®s, ®s); -} - -int -MGenWait(void) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_WAIT_ORD << 16 | MGENVXD_DEVICE_ID; - int386(CHUNNEL_INT, ®s, ®s); - return regs.d.eax; -} - -int MGenGetQueueCtr(int qNo) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = qNo; - int386(CHUNNEL_INT, ®s, ®s); - - return regs.d.eax; -} - -RTQ_NODE *MGenMoveTo(int qFrom, int qTo) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = qFrom; - regs.d.ecx = qTo; - int386(CHUNNEL_INT, ®s, ®s); - - return (RTQ_NODE *) regs.d.eax; -} - -RTQ_NODE *MGenGetNode(int q) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = q; - int386(CHUNNEL_INT, ®s, ®s); - - return (RTQ_NODE *) regs.d.eax; -} - -RTQ_NODE *MGenGetMasterNode(unsigned *size) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID; - int386(CHUNNEL_INT, ®s, ®s); - *size = regs.d.ecx; - - return (RTQ_NODE *) regs.d.eax; -} - -RTQ_NODE *MGenFlushNodes(int qFrom, int qTo) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = qFrom; - regs.d.ecx = qTo; - int386(CHUNNEL_INT, ®s, ®s); - - return (RTQ_NODE *) regs.d.eax; -} - -int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID; - regs.d.ebx = lowerOrderBits; - regs.d.ecx = upperOrderBits; - int386(CHUNNEL_INT, ®s, ®s); - - return regs.d.eax; -} - -int MGenSanityCheck(void) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID; - int386(CHUNNEL_INT, ®s, ®s); - - return regs.d.eax; -} - -void MGenWakeupDll(void) -{ - REGISTERS regs; - - regs.d.eax = MGENVXD_WAKEUPDLL_ORD << 16 | MGENVXD_DEVICE_ID; - int386(CHUNNEL_INT, ®s, ®s); -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include + +//#include "types.h" +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +//#include "mgenord.h" +#define MGENVXD_REGISTER_ORD 1 +#define MGENVXD_GETMEM_ORD 2 +#define MGENVXD_DEREGISTER_ORD 3 +#define MGENVXD_WAKEUP_ORD 4 +#define MGENVXD_MAKEDQS_ORD 5 + + +// Virtual 8086 API Ordinals +#define V86API_GETSELECTOR16_ORD (1) +#define V86API_GETSELECTOR32_ORD (2) +#define V86API_GETFLAT32_ORD (3) +#define V86API_MOVERP_ORD (6) +#define V86API_MOVEPR_ORD (7) +#define V86API_POST_ORD (8) +#define V86API_INIT_ORD (9) +#define V86API_UNINIT_ORD (10) +#define V86API_INSERTKEY_ORD (11) +#define V86API_REMOVEHOTKEY_ORD (12) +#define V86API_INSTALLHOTKEY_ORD (13) +#define V86API_HOOKINT48_ORD (14) +#define V86API_WAKEUPDLL_ORD (15) + +#define DPMIAPI_GETFLAT32_ORD (1) +#define DPMIAPI_POST_WINDOWS_ORD (2) +// these are DPMI functions. Make sure they don't clash with the +// other MGENVXD_XXXX functions above, or the DPMI functions! +#define MGENVXD_GETQUEUECTR_ORD 6 +#define MGENVXD_MOVENODE_ORD 7 +#define MGENVXD_GETNODE_ORD 8 +#define MGENVXD_FLUSHNODE_ORD 9 +#define MGENVXD_MCOUNT_ORD 10 +#define MGENVXD_MASTERNODE_ORD 11 +#define MGENVXD_SANITYCHECK_ORD 12 +#define MGENVXD_WAKEUPDLL_ORD 13 +#define MGENVXD_WAIT_ORD 14 + +// +#define HWND_OFFSET (0) +#define UMSG_OFFSET (1) +#define SIZEREQUEST_OFFSET (2) +#define HVXD_OFFSET (3) +#define DATUM_OFFSET (4) +#define SLOT_OFFSET (5) +#define SIZEGIVEN_OFFSET (6) +#define SELECTOR32_OFFSET (7) +#define SELECTOR16_OFFSET (8) + +//#include "magic.h" +#define MGENVXD_DEVICE_ID 0x18AA + +//#include "rtq.h" +#define RTQ_NODE struct rtq_node + +RTQ_NODE + { + RTQ_NODE *self; // Ring zero address of this node + RTQ_NODE *left; // Ring zero address of preceding node + RTQ_NODE *right; // Ring zero address of succeding node + BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface) + BYTE * rtqInsert; // Ring 3 insertion position + WORD rtqLen; // Length of buffer, excluding preface + WORD rtqUpCtr; // Up Counter of bytes used so far + WORD rtqQCtr; // number of nodes attached + WORD padding; // DWORD alignment + }; + +#define RTQ_PARAM_MOVENODE struct rtq_param_movenode +RTQ_PARAM_MOVENODE + { + WORD rtqFromDQ; + WORD rtqToDQ; + }; + +RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From + +int _int86(int vector, __dpmi_regs *iregs, __dpmi_regs *oregs); + +#define CHUNNEL_INT 0x48 + +#define int386 _int86 +#define REGISTERS __dpmi_regs + +void +Yield(void) +{ + __dpmi_yield(); +} + +void +PostWindowsMessage(void) +{ + REGISTERS regs; + + regs.d.eax = DPMIAPI_POST_WINDOWS_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = 0; + regs.d.ecx = 0; + int386(CHUNNEL_INT, ®s, ®s); +} + +int +MGenWait(void) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_WAIT_ORD << 16 | MGENVXD_DEVICE_ID; + int386(CHUNNEL_INT, ®s, ®s); + return regs.d.eax; +} + +int MGenGetQueueCtr(int qNo) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_GETQUEUECTR_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = qNo; + int386(CHUNNEL_INT, ®s, ®s); + + return regs.d.eax; +} + +RTQ_NODE *MGenMoveTo(int qFrom, int qTo) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_MOVENODE_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = qFrom; + regs.d.ecx = qTo; + int386(CHUNNEL_INT, ®s, ®s); + + return (RTQ_NODE *) regs.d.eax; +} + +RTQ_NODE *MGenGetNode(int q) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_GETNODE_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = q; + int386(CHUNNEL_INT, ®s, ®s); + + return (RTQ_NODE *) regs.d.eax; +} + +RTQ_NODE *MGenGetMasterNode(unsigned *size) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_MASTERNODE_ORD << 16 | MGENVXD_DEVICE_ID; + int386(CHUNNEL_INT, ®s, ®s); + *size = regs.d.ecx; + + return (RTQ_NODE *) regs.d.eax; +} + +RTQ_NODE *MGenFlushNodes(int qFrom, int qTo) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_FLUSHNODE_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = qFrom; + regs.d.ecx = qTo; + int386(CHUNNEL_INT, ®s, ®s); + + return (RTQ_NODE *) regs.d.eax; +} + +int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_MCOUNT_ORD << 16 | MGENVXD_DEVICE_ID; + regs.d.ebx = lowerOrderBits; + regs.d.ecx = upperOrderBits; + int386(CHUNNEL_INT, ®s, ®s); + + return regs.d.eax; +} + +int MGenSanityCheck(void) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_SANITYCHECK_ORD << 16 | MGENVXD_DEVICE_ID; + int386(CHUNNEL_INT, ®s, ®s); + + return regs.d.eax; +} + +void MGenWakeupDll(void) +{ + REGISTERS regs; + + regs.d.eax = MGENVXD_WAKEUPDLL_ORD << 16 | MGENVXD_DEVICE_ID; + int386(CHUNNEL_INT, ®s, ®s); +} diff --git a/WinQuake/mplpc.c b/WinQuake/mplpc.c index 10bc564..57d2ffd 100644 --- a/WinQuake/mplpc.c +++ b/WinQuake/mplpc.c @@ -1,1001 +1,1001 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include -#include "mpdosock.h" - -//#include "types.h" -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; - -//#include "lpc.h" -typedef struct { - short version; // version of LPC requested - short sizeOfArgs; // size of arguments - short service; // service # requested - char Data[1]; // data -} LPCData; - -typedef struct { - short version; // LPC version - short sizeOfReturn; // return data size - short error; // any error codes - short noRet; // number of returns - char Data[1]; // data -} LPCReturn; - -//#include "services.h" -#define MAXSOCKETS 20 - -// services -#define LPC_SOCKBIND 4 -#define LPC_SOCKGETHOSTBYNAME 5 -#define LPC_SOCKGETHOSTNAME 6 -#define LPC_SOCKGETHOSTBYADDR 7 -#define LPC_SOCKCLOSE 8 -#define LPC_SOCKSOCKET 9 -#define LPC_SOCKRECVFROM 10 -#define LPC_SOCKSENDTO 11 -#define LPC_SOCKIOCTL 12 -#define LPC_SOCKGETSOCKNAME 13 -#define LPC_SOCKFLUSH 14 -#define LPC_SOCKSETOPT 15 -#define LPC_SOCKGETLASTERROR 16 -#define LPC_SOCKINETADDR 17 - -// htons, ntohs, htonl, ntohl implemented locally - -// errors -#define LPC_UNRECOGNIZED_SERVICE -1 -#define LPC_NOERROR 0 - -// structures for support -typedef struct { - SOCKET s; - int namelen; - char name[1]; -} BindArgs; - -typedef struct { - SOCKET s; - long cmd; - char data[1]; -} IoctlArgs; - -typedef struct { - int retVal; - int namelen; - char name[1]; -} GetSockNameRet; - -typedef GetSockNameRet GetHostNameRet; - -typedef struct { - int retVal; - int h_addr_0; // that's the only important value -} GetHostByNameRet; - -typedef struct { - int len; - int type; - char addr[1]; -} GetHostByAddrArgs; - -typedef struct { - int retVal; - char h_name[1]; // h_name is the only important value -} GetHostByAddrRet; - -typedef struct { - SOCKET s; - int flags; -} RecvFromArgs; - -typedef struct { - int retVal; - int errCode; - int len; // message len - struct sockaddr sockaddr; - int sockaddrlen; - char Data[1]; -} RecvFromRet; - -typedef struct { - SOCKET s; - int flags; - int len; - struct sockaddr sockaddr; - int sockaddrlen; - char Data[1]; -} SendToArgs; - -typedef struct { - int retVal; - int errCode; -} SendToRet; - -typedef struct { - int bufflen; - SOCKET s; - int len; - int sockaddrlen; - struct sockaddr address; - char data[1]; -} SocketChannelData; - -typedef struct { - int af; - int type; - int protocol; -} SocketArgs; - -typedef struct { - SOCKET s; - int len; - int flags; - int addrlen; - struct sockaddr addr; - char data[1]; -} WinSockData; - -typedef struct { - SOCKET s; - int level; - int optname; - int optlen; - char optval[1]; -} SetSockOptArgs; - -typedef struct { - SOCKET sock[MAXSOCKETS]; -} SocketMap; - -//#include "rtq.h" -#define RTQ_NODE struct rtq_node - -RTQ_NODE - { - RTQ_NODE *self; // Ring zero address of this node - RTQ_NODE *left; // Ring zero address of preceding node - RTQ_NODE *right; // Ring zero address of succeding node - BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface) - BYTE * rtqInsert; // Ring 3 insertion position - WORD rtqLen; // Length of buffer, excluding preface - WORD rtqUpCtr; // Up Counter of bytes used so far - WORD rtqQCtr; // number of nodes attached - WORD padding; // DWORD alignment - }; - -#define RTQ_PARAM_MOVENODE struct rtq_param_movenode -RTQ_PARAM_MOVENODE - { - WORD rtqFromDQ; - WORD rtqToDQ; - }; - -RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From - -//#include "mplib.h" -// give up time slice -void Yield(void); -void MGenWakeupDll(void); - -// post a message to win32 side -void PostWindowsMessage(void); - -// get # of items on qNo -int MGenGetQueueCtr(int qNo); - -// move first node from qFrom to qTo -RTQ_NODE *MGenMoveTo(int qFrom, int qTo); - -// get first node from q -RTQ_NODE *MGenGetNode(int q); - -// get master node, returning size of RTQ_NODE for size verification -RTQ_NODE *MGenGetMasterNode(unsigned *size); - -// move all nodes from qFrom to qTo -RTQ_NODE *MGenFlushNodes(int qFrom, int qTo); - -// count number of nodes in queues designated by bitmask -// lowerOrderBits == 0..31, upperOrderBits == 32-63 -int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits); - -// perform consistency check on chunnel address space -int MGenSanityCheck(void); - -#include -#include - -extern short flat_selector; - -#define SOCKET_MAP_QUEUE 41 - -#define IDLE_QUEUE 44 -#define REC_QUEUE 45 -#define SEND_QUEUE 46 - -// queue sizes -#define FREEQBASE 58 -#define FREEQ64 58 -#define FREEQ128 59 -#define FREEQ256 60 -#define FREEQ512 61 -#define FREEQ1024 62 -#define FREEQ2048 63 - -#define NFREEQ 6 - -#define QLIMIT 10 - -#define PRIVATEQ 50 - -#define FARPKL(x) (_farnspeekl((unsigned long) x)) -#define FARPKB(x) (_farnspeekb((unsigned long) x)) -#define FARPKS(x) (_farnspeekw((unsigned long) x)) - -#define FARPOKL(x, y) (_farnspokel((unsigned long) x, (unsigned long) y)) -#define FARPOKB(x, y) (_farnspokeb((unsigned long) x, (unsigned char) y)) - -int Qsizes[] = { 64, 128, 256, 512, 1024, 2048 }; - -int SocketError = 0; - -SocketMap *SockMap; - -#define HOSTENT_ALIAS_LIMIT 5 -#define HOSTENT_STRLEN_LIMIT 50 -#define HOSTENT_ADDR_LIST_LIMIT 5 - -struct hostent HostEnt; - -char HostEnt_hname[HOSTENT_STRLEN_LIMIT]; -char *HostEnt_h_aliases[HOSTENT_ALIAS_LIMIT]; -char HostEnt_names[HOSTENT_ALIAS_LIMIT][HOSTENT_STRLEN_LIMIT]; -struct in_addr* HostEnt_addr_list[HOSTENT_ADDR_LIST_LIMIT]; -struct in_addr HostEnt_addrs[HOSTENT_ADDR_LIST_LIMIT]; - -void -fmemcpyto(void *to, const void *from, int length) -{ - movedata(_my_ds(), (unsigned)from, flat_selector, (unsigned)to, length); -} - -void -fmemcpyfrom(void *to, const void *from, int length) -{ - movedata(flat_selector, (unsigned)from, _my_ds(), (unsigned)to, length); -} - -void -fstrcpyto(char *to, const char *from) -{ - while (*from) { - FARPOKB(to, *from); - to++; from++; - } - FARPOKB(to, 0); -} - -void -fstrncpyto(char *to, const char *from, int len) -{ - while (*from && len) { - FARPOKB(to, *from); - to++; from++; len--; - } - FARPOKB(to, 0); -} - -void -fstrcpyfrom(char *to, const char *from) -{ - while (FARPKB(from)) { - *to = FARPKB(from); - from++; to++; - } - *to = 0; -} - -void -fstrncpyfrom(char *to, const char *from, int len) -{ - while (FARPKB(from) && len) { - *to = FARPKB(from); - from++; to++; len--; - } - *to = 0; -} - -void -GetSocketMap(void) -{ - RTQ_NODE *n = MGenGetNode(SOCKET_MAP_QUEUE); - - SockMap = (SocketMap *) FARPKL(&n->rtqDatum); -} - -void * -GetFreeBufferToQueue(int q, int bufSize) -{ - int i; - - for (i = 0; i < NFREEQ; i++) { - if (Qsizes[i] >= bufSize && MGenGetQueueCtr(i+FREEQBASE)) { - RTQ_NODE *n = MGenMoveTo(i+FREEQBASE, q); - if (!n) - continue; - FARPOKL(&n->rtqUpCtr, bufSize); - return (void *) FARPKL(&n->rtqDatum); - } - } - - return 0; -} - -void -FreeBufferFromQueue(int q) -{ - int i; - RTQ_NODE *n = MGenGetNode(q); - - for (i = 0; i < NFREEQ; i++) { - if (Qsizes[i] == FARPKS(&n->rtqLen)) { - MGenMoveTo(q, i+FREEQBASE); - return; - } - } -} - -void -SetLPCData(LPCData *lpc) -{ - - FARPOKL(&(lpc->version), 1); - FARPOKL(&(lpc->sizeOfArgs), 0); - FARPOKL(&(lpc->service), 0); -} - -int -bind(SOCKET s, const struct sockaddr *name, int namelen) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - BindArgs *bargs; - int retVal; - - _farsetsel(flat_selector); - SocketError = 0; - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKBIND); - bargs = (BindArgs *) p->Data; - FARPOKL(&bargs->s, s); - FARPOKL(&bargs->namelen, namelen); - fmemcpyto(bargs->name, name, namelen); - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -int -closesocket(SOCKET s) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - int retVal; - - _farsetsel(flat_selector); - SocketError = 0; - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKCLOSE); - FARPOKL(p->Data, s); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -void -ZapHostEnt() -{ - // do nothing -} - -void -ReconstructHostEnt(struct hostent *s, void *flattened) -{ - struct hostent *old = (struct hostent *) flattened; - int i; - char **ptr; - - - s->h_name = HostEnt_hname; - fstrncpyfrom(s->h_name, (char *) FARPKL(&old->h_name), HOSTENT_STRLEN_LIMIT-1); - s->h_name[HOSTENT_STRLEN_LIMIT-1] = 0; - - s->h_aliases = HostEnt_h_aliases; - ptr = (char **) FARPKL(&old->h_aliases); - for (i = 0; i < (HOSTENT_ALIAS_LIMIT-1) && FARPKL(ptr); i++, ptr++) { - s->h_aliases[i] = HostEnt_names[i]; - // fstrncpyfrom(s->h_aliases[i], (void *) FARPKL(ptr), HOSTENT_STRLEN_LIMIT-1); - s->h_aliases[i][HOSTENT_STRLEN_LIMIT-1] = 0; - } - s->h_aliases[i] = 0; - - s->h_addrtype = FARPKS(&old->h_addrtype); - s->h_length = FARPKS(&old->h_length); - - if (FARPKS(&old->h_length) != sizeof(struct in_addr)) { - printf("Error!\n"); - exit(0); - } - - s->h_addr_list = (char **) HostEnt_addr_list; - ptr = (char **) FARPKL(&old->h_addr_list); - for (i = 0; i < (HOSTENT_ADDR_LIST_LIMIT - 1) && FARPKL(ptr); i++, ptr++) { - s->h_addr_list[i] = (char *) &(HostEnt_addrs[i]); - fmemcpyfrom(s->h_addr_list[i], (void *) FARPKL(ptr), s->h_length); - } - s->h_addr_list[i] = 0; -} - - -int -getsockname(SOCKET s, struct sockaddr *name, int *namelen) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - GetSockNameRet *ret; - int retVal; - - SocketError = 0; - _farsetsel(flat_selector); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKGETSOCKNAME); - FARPOKL(p->Data, s); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - ret = (GetSockNameRet *) r->Data; - retVal = FARPKL(&ret->retVal); - fmemcpyfrom(name, ret->name, FARPKL(&ret->namelen)); - *namelen = FARPKL(&ret->namelen); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -int -gethostname(char *name, int namelen) -{ - RTQ_NODE *n; - LPCData *p; - LPCReturn *r; - GetHostNameRet *ret; - int retVal; - char *s; - - _farsetsel(flat_selector); - SocketError = 0; - n = (RTQ_NODE *) MGenGetNode(IDLE_QUEUE); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service,LPC_SOCKGETHOSTNAME); - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = (RTQ_NODE *) (MGenGetNode(REC_QUEUE))) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - ret = (GetHostNameRet *) r->Data; - - retVal = FARPKL(&ret->retVal); - - s = ret->name; - - fstrncpyfrom(name, s, namelen); - -#if 0 - len = strlen(ret->name); - - if (len > namelen) - memcpy(name, ret->name, ret->namelen); - else - strcpy(name, ret->name); -#endif - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -struct hostent * -gethostbyname(const char *name) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - struct hostent *retVal; - - _farsetsel(flat_selector); - SocketError = 0; - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKGETHOSTBYNAME); - fstrcpyto(p->Data, name); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - retVal = (struct hostent *) r->Data; - - if (FARPKL(&retVal->h_name) == 0) { - retVal = 0; - } else { - ZapHostEnt(); - ReconstructHostEnt(&HostEnt, (void *) retVal); - retVal = &HostEnt; - } - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -struct hostent * -gethostbyaddr(const char *addr, int len, int type) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - GetHostByAddrArgs *args; - struct hostent *retVal; - - SocketError = 0; - _farsetsel(flat_selector); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKGETHOSTBYADDR); - args = (GetHostByAddrArgs *) p->Data; - FARPOKL(&args->len, len); - FARPOKL(&args->type, type); - fmemcpyto(args->addr, addr, len); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - r = (LPCReturn *) FARPKL(&n->rtqDatum); - retVal = (struct hostent *) r->Data; - - if (FARPKL(&retVal->h_name) == 0) { - retVal = 0; - } else { - ZapHostEnt(); - - ReconstructHostEnt(&HostEnt, (void *) retVal); - retVal = &HostEnt; - } - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - - -SOCKET -socket(int af, int type, int protocol) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - SocketArgs *args; - int retVal; - - _farsetsel(flat_selector); - SocketError = 0; - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKSOCKET); - args = (SocketArgs *) p->Data; - FARPOKL(&args->af, af); - FARPOKL(&args->type, type); - FARPOKL(&args->protocol, protocol); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -void -sockets_flush(void) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - - SocketError = 0; - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKFLUSH); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); -} - -int -recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, - int *fromlen) -{ - int i; - RTQ_NODE *n; - WinSockData *data; - int bytesRead; - - SocketError = 0; - _farsetsel(flat_selector); - if (!SockMap) - GetSocketMap(); - - for (i = 0; i < MAXSOCKETS; i++) { - if (FARPKL(&(SockMap->sock[i])) == s) - break; - } - - if (i == MAXSOCKETS) - return SOCKET_ERROR; - - // pick up node - n = MGenGetNode(i); - if (n == 0) { - SocketError = WSAEWOULDBLOCK; - return -1; - } - - data = (WinSockData *) FARPKL(&n->rtqDatum); - bytesRead = FARPKL(&data->len); - - if (from) { - fmemcpyfrom(from, &data->addr, sizeof(struct sockaddr)); - } - - if (fromlen) { - *fromlen = FARPKL(&data->addrlen); - } - - fmemcpyfrom(buf, data->data, len > bytesRead ? bytesRead : len); - - if ((flags & MSG_PEEK) == 0) { - FreeBufferFromQueue(i); - } - - return bytesRead; -} - -int -sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen) -{ - int i; - int outQ; - WinSockData *data; - - SocketError = 0; - _farsetsel(flat_selector); - if (!SockMap) - GetSocketMap(); - - for (i = 0; i < MAXSOCKETS; i++) { - if (FARPKL(&SockMap->sock[i]) == s) { - break; - } - } - - if (i == MAXSOCKETS) { - SocketError = WSAENOTSOCK; - return SOCKET_ERROR; - } - - outQ = i + MAXSOCKETS; - - if (MGenGetQueueCtr(outQ) >= QLIMIT) { - SocketError = WSAEWOULDBLOCK; - return SOCKET_ERROR; - } - - data = GetFreeBufferToQueue(PRIVATEQ, len + sizeof(WinSockData)); - - if (!data) { - SocketError = WSAEWOULDBLOCK; - return SOCKET_ERROR; - } - - FARPOKL(&data->s, s); - FARPOKL(&data->len, len); - if (to) { - fmemcpyto(&data->addr, to, tolen); - FARPOKL(&data->addrlen, tolen); - } else { - FARPOKL(&data->addrlen, 0); - } - - FARPOKL(&data->flags, flags); - - fmemcpyto(data->data, buf, len); - - MGenMoveTo(PRIVATEQ, outQ); - - return len; -} - -int -ioctlsocket(SOCKET s, long cmd, unsigned long *argp) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - IoctlArgs *args; - int retVal; - - SocketError = 0; - _farsetsel(flat_selector); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKIOCTL); - args = (IoctlArgs *) p->Data; - FARPOKL(&args->s, s); - FARPOKL(&args->cmd, cmd); - - switch(cmd) { - case FIONBIO: - FARPOKL(args->data, *argp); - break; - default: - return SOCKET_ERROR; - } - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -int -setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - SetSockOptArgs *args; - int retVal; - - SocketError = 0; - _farsetsel(flat_selector); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKSETOPT); - args = (SetSockOptArgs *) p->Data; - FARPOKL(&args->s, s); - FARPOKL(&args->level, level); - FARPOKL(&args->optname, optname); - FARPOKL(&args->optlen, optlen); - fmemcpyto(args->optval, optval, optlen); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -int -WSAGetLastError(void) -{ - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - int retVal; - - - _farsetsel(flat_selector); - if (SocketError) { - int err = SocketError; - - SocketError = 0; - return err; - } - - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKGETLASTERROR); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; -} - -unsigned long inet_addr(const char *cp) -{ - int ret; - unsigned int ha1, ha2, ha3, ha4; - unsigned long ipaddr; - - ret = sscanf(cp, "%d.%d.%d.%d", &ha1, &ha2, &ha3, &ha4); - if (ret != 4) - return -1; - ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; - return ipaddr; -#if 0 - RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); - LPCData *p; - LPCReturn *r; - int retVal; - - SocketError = 0; - _farsetsel(flat_selector); - p = (LPCData *) FARPKL(&n->rtqDatum); - SetLPCData(p); - FARPOKL(&p->service, LPC_SOCKINETADDR); - - fstrcpyto(p->Data, cp); - - MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); - PostWindowsMessage(); - - while ((n = MGenGetNode(REC_QUEUE)) == 0) - Yield(); - - r = (LPCReturn *) FARPKL(&n->rtqDatum); - - if (FARPKS(&r->error) != LPC_NOERROR) { - return -1; - } - - retVal = FARPKL(r->Data); - - // get ready for next call - MGenMoveTo(REC_QUEUE, IDLE_QUEUE); - - return retVal; - #endif -} - -char *inet_ntoa (struct in_addr in) -{ - static char buf [32]; - - sprintf(buf, "%u.%u.%u.%u", in.S_un.S_un_b.s_b1, in.S_un.S_un_b.s_b2, in.S_un.S_un_b.s_b3, in.S_un.S_un_b.s_b4); - return buf; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include +#include "mpdosock.h" + +//#include "types.h" +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +//#include "lpc.h" +typedef struct { + short version; // version of LPC requested + short sizeOfArgs; // size of arguments + short service; // service # requested + char Data[1]; // data +} LPCData; + +typedef struct { + short version; // LPC version + short sizeOfReturn; // return data size + short error; // any error codes + short noRet; // number of returns + char Data[1]; // data +} LPCReturn; + +//#include "services.h" +#define MAXSOCKETS 20 + +// services +#define LPC_SOCKBIND 4 +#define LPC_SOCKGETHOSTBYNAME 5 +#define LPC_SOCKGETHOSTNAME 6 +#define LPC_SOCKGETHOSTBYADDR 7 +#define LPC_SOCKCLOSE 8 +#define LPC_SOCKSOCKET 9 +#define LPC_SOCKRECVFROM 10 +#define LPC_SOCKSENDTO 11 +#define LPC_SOCKIOCTL 12 +#define LPC_SOCKGETSOCKNAME 13 +#define LPC_SOCKFLUSH 14 +#define LPC_SOCKSETOPT 15 +#define LPC_SOCKGETLASTERROR 16 +#define LPC_SOCKINETADDR 17 + +// htons, ntohs, htonl, ntohl implemented locally + +// errors +#define LPC_UNRECOGNIZED_SERVICE -1 +#define LPC_NOERROR 0 + +// structures for support +typedef struct { + SOCKET s; + int namelen; + char name[1]; +} BindArgs; + +typedef struct { + SOCKET s; + long cmd; + char data[1]; +} IoctlArgs; + +typedef struct { + int retVal; + int namelen; + char name[1]; +} GetSockNameRet; + +typedef GetSockNameRet GetHostNameRet; + +typedef struct { + int retVal; + int h_addr_0; // that's the only important value +} GetHostByNameRet; + +typedef struct { + int len; + int type; + char addr[1]; +} GetHostByAddrArgs; + +typedef struct { + int retVal; + char h_name[1]; // h_name is the only important value +} GetHostByAddrRet; + +typedef struct { + SOCKET s; + int flags; +} RecvFromArgs; + +typedef struct { + int retVal; + int errCode; + int len; // message len + struct sockaddr sockaddr; + int sockaddrlen; + char Data[1]; +} RecvFromRet; + +typedef struct { + SOCKET s; + int flags; + int len; + struct sockaddr sockaddr; + int sockaddrlen; + char Data[1]; +} SendToArgs; + +typedef struct { + int retVal; + int errCode; +} SendToRet; + +typedef struct { + int bufflen; + SOCKET s; + int len; + int sockaddrlen; + struct sockaddr address; + char data[1]; +} SocketChannelData; + +typedef struct { + int af; + int type; + int protocol; +} SocketArgs; + +typedef struct { + SOCKET s; + int len; + int flags; + int addrlen; + struct sockaddr addr; + char data[1]; +} WinSockData; + +typedef struct { + SOCKET s; + int level; + int optname; + int optlen; + char optval[1]; +} SetSockOptArgs; + +typedef struct { + SOCKET sock[MAXSOCKETS]; +} SocketMap; + +//#include "rtq.h" +#define RTQ_NODE struct rtq_node + +RTQ_NODE + { + RTQ_NODE *self; // Ring zero address of this node + RTQ_NODE *left; // Ring zero address of preceding node + RTQ_NODE *right; // Ring zero address of succeding node + BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface) + BYTE * rtqInsert; // Ring 3 insertion position + WORD rtqLen; // Length of buffer, excluding preface + WORD rtqUpCtr; // Up Counter of bytes used so far + WORD rtqQCtr; // number of nodes attached + WORD padding; // DWORD alignment + }; + +#define RTQ_PARAM_MOVENODE struct rtq_param_movenode +RTQ_PARAM_MOVENODE + { + WORD rtqFromDQ; + WORD rtqToDQ; + }; + +RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From + +//#include "mplib.h" +// give up time slice +void Yield(void); +void MGenWakeupDll(void); + +// post a message to win32 side +void PostWindowsMessage(void); + +// get # of items on qNo +int MGenGetQueueCtr(int qNo); + +// move first node from qFrom to qTo +RTQ_NODE *MGenMoveTo(int qFrom, int qTo); + +// get first node from q +RTQ_NODE *MGenGetNode(int q); + +// get master node, returning size of RTQ_NODE for size verification +RTQ_NODE *MGenGetMasterNode(unsigned *size); + +// move all nodes from qFrom to qTo +RTQ_NODE *MGenFlushNodes(int qFrom, int qTo); + +// count number of nodes in queues designated by bitmask +// lowerOrderBits == 0..31, upperOrderBits == 32-63 +int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits); + +// perform consistency check on chunnel address space +int MGenSanityCheck(void); + +#include +#include + +extern short flat_selector; + +#define SOCKET_MAP_QUEUE 41 + +#define IDLE_QUEUE 44 +#define REC_QUEUE 45 +#define SEND_QUEUE 46 + +// queue sizes +#define FREEQBASE 58 +#define FREEQ64 58 +#define FREEQ128 59 +#define FREEQ256 60 +#define FREEQ512 61 +#define FREEQ1024 62 +#define FREEQ2048 63 + +#define NFREEQ 6 + +#define QLIMIT 10 + +#define PRIVATEQ 50 + +#define FARPKL(x) (_farnspeekl((unsigned long) x)) +#define FARPKB(x) (_farnspeekb((unsigned long) x)) +#define FARPKS(x) (_farnspeekw((unsigned long) x)) + +#define FARPOKL(x, y) (_farnspokel((unsigned long) x, (unsigned long) y)) +#define FARPOKB(x, y) (_farnspokeb((unsigned long) x, (unsigned char) y)) + +int Qsizes[] = { 64, 128, 256, 512, 1024, 2048 }; + +int SocketError = 0; + +SocketMap *SockMap; + +#define HOSTENT_ALIAS_LIMIT 5 +#define HOSTENT_STRLEN_LIMIT 50 +#define HOSTENT_ADDR_LIST_LIMIT 5 + +struct hostent HostEnt; + +char HostEnt_hname[HOSTENT_STRLEN_LIMIT]; +char *HostEnt_h_aliases[HOSTENT_ALIAS_LIMIT]; +char HostEnt_names[HOSTENT_ALIAS_LIMIT][HOSTENT_STRLEN_LIMIT]; +struct in_addr* HostEnt_addr_list[HOSTENT_ADDR_LIST_LIMIT]; +struct in_addr HostEnt_addrs[HOSTENT_ADDR_LIST_LIMIT]; + +void +fmemcpyto(void *to, const void *from, int length) +{ + movedata(_my_ds(), (unsigned)from, flat_selector, (unsigned)to, length); +} + +void +fmemcpyfrom(void *to, const void *from, int length) +{ + movedata(flat_selector, (unsigned)from, _my_ds(), (unsigned)to, length); +} + +void +fstrcpyto(char *to, const char *from) +{ + while (*from) { + FARPOKB(to, *from); + to++; from++; + } + FARPOKB(to, 0); +} + +void +fstrncpyto(char *to, const char *from, int len) +{ + while (*from && len) { + FARPOKB(to, *from); + to++; from++; len--; + } + FARPOKB(to, 0); +} + +void +fstrcpyfrom(char *to, const char *from) +{ + while (FARPKB(from)) { + *to = FARPKB(from); + from++; to++; + } + *to = 0; +} + +void +fstrncpyfrom(char *to, const char *from, int len) +{ + while (FARPKB(from) && len) { + *to = FARPKB(from); + from++; to++; len--; + } + *to = 0; +} + +void +GetSocketMap(void) +{ + RTQ_NODE *n = MGenGetNode(SOCKET_MAP_QUEUE); + + SockMap = (SocketMap *) FARPKL(&n->rtqDatum); +} + +void * +GetFreeBufferToQueue(int q, int bufSize) +{ + int i; + + for (i = 0; i < NFREEQ; i++) { + if (Qsizes[i] >= bufSize && MGenGetQueueCtr(i+FREEQBASE)) { + RTQ_NODE *n = MGenMoveTo(i+FREEQBASE, q); + if (!n) + continue; + FARPOKL(&n->rtqUpCtr, bufSize); + return (void *) FARPKL(&n->rtqDatum); + } + } + + return 0; +} + +void +FreeBufferFromQueue(int q) +{ + int i; + RTQ_NODE *n = MGenGetNode(q); + + for (i = 0; i < NFREEQ; i++) { + if (Qsizes[i] == FARPKS(&n->rtqLen)) { + MGenMoveTo(q, i+FREEQBASE); + return; + } + } +} + +void +SetLPCData(LPCData *lpc) +{ + + FARPOKL(&(lpc->version), 1); + FARPOKL(&(lpc->sizeOfArgs), 0); + FARPOKL(&(lpc->service), 0); +} + +int +bind(SOCKET s, const struct sockaddr *name, int namelen) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + BindArgs *bargs; + int retVal; + + _farsetsel(flat_selector); + SocketError = 0; + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKBIND); + bargs = (BindArgs *) p->Data; + FARPOKL(&bargs->s, s); + FARPOKL(&bargs->namelen, namelen); + fmemcpyto(bargs->name, name, namelen); + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +int +closesocket(SOCKET s) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + int retVal; + + _farsetsel(flat_selector); + SocketError = 0; + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKCLOSE); + FARPOKL(p->Data, s); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +void +ZapHostEnt() +{ + // do nothing +} + +void +ReconstructHostEnt(struct hostent *s, void *flattened) +{ + struct hostent *old = (struct hostent *) flattened; + int i; + char **ptr; + + + s->h_name = HostEnt_hname; + fstrncpyfrom(s->h_name, (char *) FARPKL(&old->h_name), HOSTENT_STRLEN_LIMIT-1); + s->h_name[HOSTENT_STRLEN_LIMIT-1] = 0; + + s->h_aliases = HostEnt_h_aliases; + ptr = (char **) FARPKL(&old->h_aliases); + for (i = 0; i < (HOSTENT_ALIAS_LIMIT-1) && FARPKL(ptr); i++, ptr++) { + s->h_aliases[i] = HostEnt_names[i]; + // fstrncpyfrom(s->h_aliases[i], (void *) FARPKL(ptr), HOSTENT_STRLEN_LIMIT-1); + s->h_aliases[i][HOSTENT_STRLEN_LIMIT-1] = 0; + } + s->h_aliases[i] = 0; + + s->h_addrtype = FARPKS(&old->h_addrtype); + s->h_length = FARPKS(&old->h_length); + + if (FARPKS(&old->h_length) != sizeof(struct in_addr)) { + printf("Error!\n"); + exit(0); + } + + s->h_addr_list = (char **) HostEnt_addr_list; + ptr = (char **) FARPKL(&old->h_addr_list); + for (i = 0; i < (HOSTENT_ADDR_LIST_LIMIT - 1) && FARPKL(ptr); i++, ptr++) { + s->h_addr_list[i] = (char *) &(HostEnt_addrs[i]); + fmemcpyfrom(s->h_addr_list[i], (void *) FARPKL(ptr), s->h_length); + } + s->h_addr_list[i] = 0; +} + + +int +getsockname(SOCKET s, struct sockaddr *name, int *namelen) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + GetSockNameRet *ret; + int retVal; + + SocketError = 0; + _farsetsel(flat_selector); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKGETSOCKNAME); + FARPOKL(p->Data, s); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + ret = (GetSockNameRet *) r->Data; + retVal = FARPKL(&ret->retVal); + fmemcpyfrom(name, ret->name, FARPKL(&ret->namelen)); + *namelen = FARPKL(&ret->namelen); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +int +gethostname(char *name, int namelen) +{ + RTQ_NODE *n; + LPCData *p; + LPCReturn *r; + GetHostNameRet *ret; + int retVal; + char *s; + + _farsetsel(flat_selector); + SocketError = 0; + n = (RTQ_NODE *) MGenGetNode(IDLE_QUEUE); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service,LPC_SOCKGETHOSTNAME); + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = (RTQ_NODE *) (MGenGetNode(REC_QUEUE))) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + ret = (GetHostNameRet *) r->Data; + + retVal = FARPKL(&ret->retVal); + + s = ret->name; + + fstrncpyfrom(name, s, namelen); + +#if 0 + len = strlen(ret->name); + + if (len > namelen) + memcpy(name, ret->name, ret->namelen); + else + strcpy(name, ret->name); +#endif + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +struct hostent * +gethostbyname(const char *name) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + struct hostent *retVal; + + _farsetsel(flat_selector); + SocketError = 0; + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKGETHOSTBYNAME); + fstrcpyto(p->Data, name); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + retVal = (struct hostent *) r->Data; + + if (FARPKL(&retVal->h_name) == 0) { + retVal = 0; + } else { + ZapHostEnt(); + ReconstructHostEnt(&HostEnt, (void *) retVal); + retVal = &HostEnt; + } + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int type) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + GetHostByAddrArgs *args; + struct hostent *retVal; + + SocketError = 0; + _farsetsel(flat_selector); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKGETHOSTBYADDR); + args = (GetHostByAddrArgs *) p->Data; + FARPOKL(&args->len, len); + FARPOKL(&args->type, type); + fmemcpyto(args->addr, addr, len); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + r = (LPCReturn *) FARPKL(&n->rtqDatum); + retVal = (struct hostent *) r->Data; + + if (FARPKL(&retVal->h_name) == 0) { + retVal = 0; + } else { + ZapHostEnt(); + + ReconstructHostEnt(&HostEnt, (void *) retVal); + retVal = &HostEnt; + } + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + + +SOCKET +socket(int af, int type, int protocol) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + SocketArgs *args; + int retVal; + + _farsetsel(flat_selector); + SocketError = 0; + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKSOCKET); + args = (SocketArgs *) p->Data; + FARPOKL(&args->af, af); + FARPOKL(&args->type, type); + FARPOKL(&args->protocol, protocol); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +void +sockets_flush(void) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + + SocketError = 0; + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKFLUSH); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); +} + +int +recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, + int *fromlen) +{ + int i; + RTQ_NODE *n; + WinSockData *data; + int bytesRead; + + SocketError = 0; + _farsetsel(flat_selector); + if (!SockMap) + GetSocketMap(); + + for (i = 0; i < MAXSOCKETS; i++) { + if (FARPKL(&(SockMap->sock[i])) == s) + break; + } + + if (i == MAXSOCKETS) + return SOCKET_ERROR; + + // pick up node + n = MGenGetNode(i); + if (n == 0) { + SocketError = WSAEWOULDBLOCK; + return -1; + } + + data = (WinSockData *) FARPKL(&n->rtqDatum); + bytesRead = FARPKL(&data->len); + + if (from) { + fmemcpyfrom(from, &data->addr, sizeof(struct sockaddr)); + } + + if (fromlen) { + *fromlen = FARPKL(&data->addrlen); + } + + fmemcpyfrom(buf, data->data, len > bytesRead ? bytesRead : len); + + if ((flags & MSG_PEEK) == 0) { + FreeBufferFromQueue(i); + } + + return bytesRead; +} + +int +sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen) +{ + int i; + int outQ; + WinSockData *data; + + SocketError = 0; + _farsetsel(flat_selector); + if (!SockMap) + GetSocketMap(); + + for (i = 0; i < MAXSOCKETS; i++) { + if (FARPKL(&SockMap->sock[i]) == s) { + break; + } + } + + if (i == MAXSOCKETS) { + SocketError = WSAENOTSOCK; + return SOCKET_ERROR; + } + + outQ = i + MAXSOCKETS; + + if (MGenGetQueueCtr(outQ) >= QLIMIT) { + SocketError = WSAEWOULDBLOCK; + return SOCKET_ERROR; + } + + data = GetFreeBufferToQueue(PRIVATEQ, len + sizeof(WinSockData)); + + if (!data) { + SocketError = WSAEWOULDBLOCK; + return SOCKET_ERROR; + } + + FARPOKL(&data->s, s); + FARPOKL(&data->len, len); + if (to) { + fmemcpyto(&data->addr, to, tolen); + FARPOKL(&data->addrlen, tolen); + } else { + FARPOKL(&data->addrlen, 0); + } + + FARPOKL(&data->flags, flags); + + fmemcpyto(data->data, buf, len); + + MGenMoveTo(PRIVATEQ, outQ); + + return len; +} + +int +ioctlsocket(SOCKET s, long cmd, unsigned long *argp) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + IoctlArgs *args; + int retVal; + + SocketError = 0; + _farsetsel(flat_selector); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKIOCTL); + args = (IoctlArgs *) p->Data; + FARPOKL(&args->s, s); + FARPOKL(&args->cmd, cmd); + + switch(cmd) { + case FIONBIO: + FARPOKL(args->data, *argp); + break; + default: + return SOCKET_ERROR; + } + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +int +setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + SetSockOptArgs *args; + int retVal; + + SocketError = 0; + _farsetsel(flat_selector); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKSETOPT); + args = (SetSockOptArgs *) p->Data; + FARPOKL(&args->s, s); + FARPOKL(&args->level, level); + FARPOKL(&args->optname, optname); + FARPOKL(&args->optlen, optlen); + fmemcpyto(args->optval, optval, optlen); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +int +WSAGetLastError(void) +{ + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + int retVal; + + + _farsetsel(flat_selector); + if (SocketError) { + int err = SocketError; + + SocketError = 0; + return err; + } + + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKGETLASTERROR); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; +} + +unsigned long inet_addr(const char *cp) +{ + int ret; + unsigned int ha1, ha2, ha3, ha4; + unsigned long ipaddr; + + ret = sscanf(cp, "%d.%d.%d.%d", &ha1, &ha2, &ha3, &ha4); + if (ret != 4) + return -1; + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + return ipaddr; +#if 0 + RTQ_NODE *n = MGenGetNode(IDLE_QUEUE); + LPCData *p; + LPCReturn *r; + int retVal; + + SocketError = 0; + _farsetsel(flat_selector); + p = (LPCData *) FARPKL(&n->rtqDatum); + SetLPCData(p); + FARPOKL(&p->service, LPC_SOCKINETADDR); + + fstrcpyto(p->Data, cp); + + MGenMoveTo(IDLE_QUEUE, SEND_QUEUE); + PostWindowsMessage(); + + while ((n = MGenGetNode(REC_QUEUE)) == 0) + Yield(); + + r = (LPCReturn *) FARPKL(&n->rtqDatum); + + if (FARPKS(&r->error) != LPC_NOERROR) { + return -1; + } + + retVal = FARPKL(r->Data); + + // get ready for next call + MGenMoveTo(REC_QUEUE, IDLE_QUEUE); + + return retVal; + #endif +} + +char *inet_ntoa (struct in_addr in) +{ + static char buf [32]; + + sprintf(buf, "%u.%u.%u.%u", in.S_un.S_un_b.s_b1, in.S_un.S_un_b.s_b2, in.S_un.S_un_b.s_b3, in.S_un.S_un_b.s_b4); + return buf; +} diff --git a/WinQuake/net.h b/WinQuake/net.h index af46125..c84cef4 100644 --- a/WinQuake/net.h +++ b/WinQuake/net.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // net.h -- quake's interface to the networking layer struct qsockaddr diff --git a/WinQuake/net_bsd.c b/WinQuake/net_bsd.c index 79d62f8..2da06de 100644 --- a/WinQuake/net_bsd.c +++ b/WinQuake/net_bsd.c @@ -1,93 +1,93 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -#include "net_loop.h" -#include "net_dgrm.h" - -net_driver_t net_drivers[MAX_NET_DRIVERS] = -{ - { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown - } - , - { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown - } -}; - -int net_numdrivers = 2; - -#include "net_udp.h" - -net_landriver_t net_landrivers[MAX_NET_DRIVERS] = -{ - { - "UDP", - false, - 0, - UDP_Init, - UDP_Shutdown, - UDP_Listen, - UDP_OpenSocket, - UDP_CloseSocket, - UDP_Connect, - UDP_CheckNewConnections, - UDP_Read, - UDP_Write, - UDP_Broadcast, - UDP_AddrToString, - UDP_StringToAddr, - UDP_GetSocketAddr, - UDP_GetNameFromAddr, - UDP_GetAddrFromName, - UDP_AddrCompare, - UDP_GetSocketPort, - UDP_SetSocketPort - } -}; - -int net_numlandrivers = 1; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +#include "net_loop.h" +#include "net_dgrm.h" + +net_driver_t net_drivers[MAX_NET_DRIVERS] = +{ + { + "Loopback", + false, + Loop_Init, + Loop_Listen, + Loop_SearchForHosts, + Loop_Connect, + Loop_CheckNewConnections, + Loop_GetMessage, + Loop_SendMessage, + Loop_SendUnreliableMessage, + Loop_CanSendMessage, + Loop_CanSendUnreliableMessage, + Loop_Close, + Loop_Shutdown + } + , + { + "Datagram", + false, + Datagram_Init, + Datagram_Listen, + Datagram_SearchForHosts, + Datagram_Connect, + Datagram_CheckNewConnections, + Datagram_GetMessage, + Datagram_SendMessage, + Datagram_SendUnreliableMessage, + Datagram_CanSendMessage, + Datagram_CanSendUnreliableMessage, + Datagram_Close, + Datagram_Shutdown + } +}; + +int net_numdrivers = 2; + +#include "net_udp.h" + +net_landriver_t net_landrivers[MAX_NET_DRIVERS] = +{ + { + "UDP", + false, + 0, + UDP_Init, + UDP_Shutdown, + UDP_Listen, + UDP_OpenSocket, + UDP_CloseSocket, + UDP_Connect, + UDP_CheckNewConnections, + UDP_Read, + UDP_Write, + UDP_Broadcast, + UDP_AddrToString, + UDP_StringToAddr, + UDP_GetSocketAddr, + UDP_GetNameFromAddr, + UDP_GetAddrFromName, + UDP_AddrCompare, + UDP_GetSocketPort, + UDP_SetSocketPort + } +}; + +int net_numlandrivers = 1; diff --git a/WinQuake/net_bw.c b/WinQuake/net_bw.c index 2fb3e06..360a4ee 100644 --- a/WinQuake/net_bw.c +++ b/WinQuake/net_bw.c @@ -1,763 +1,763 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_bw.c - -#include -#include -#include - -#include "quakedef.h" -#include "dosisms.h" - - -// this section is general Unix stuff that we need - -#define EIO 5 /* I/O error */ -#define EBADS 9 -#define EWOULDBLOCK 35 /* function would block */ -#define EMSGSIZE 40 /* message to big for buffers */ -#define EPROTONOSUPPORT 43 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ -#define EPFNOSUPPORT 46 /* Protocol family not supported */ -#define EAFNOSUPPORT 47 /* Address family not supported */ -#define ECONNABORTED 53 /* User requested hangup */ -#define ENOBUFS 55 /* No buffers available */ -#define EISCONN 56 /* Socket has closed */ -#define ENOTCONN 57 /* Socket is not connected */ -#define ESHUTDOWN 58 /* Socket is closed */ -#define ETOOMANYREFS 59 /* Too many sockets open */ -#define ETIMEDOUT 60 /* Connection timed out */ -#define ECONNREFUSED 61 /* Connection refused */ - -#define AF_INET 2 /* internet */ - -#define PF_INET AF_INET - -#define SOCK_STREAM 1 /* stream */ -#define SOCK_DGRAM 2 /* datagram */ - -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 - -#define INADDR_ANY 0 - -#define SIOCDONE 0x7300 -#define FIONREAD 0x667f -#define FIONBIO 0x667e -#define FIONWIN 0x1000 -#define FIONTIN 0x2000 - -#define BRDINIT 0 -#define BRDADDR 10 - -#define MAXHOSTNAMELEN 256 - -#define SOL_SOCKET 0xffff /* options for socket level */ - -/* - * Option flags per-socket. - */ -#define SO_DEBUG 0x0001 /* turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_REUSEADDR 0x0004 /* allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_DONTROUTE 0x0010 /* just use interface addresses */ -#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ -#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ -#define SO_USEPRIV 0x4000 /* allocate from privileged port area */ -#define SO_CANTSIG 0x8000 /* prevent SIGPIPE on SS_CANTSENDMORE */ - -/* - * Additional options, not kept in so_options. - */ -#define SO_SNDBUF 0x1001 /* send buffer size */ -#define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ -#define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ERROR 0x1007 /* get error status and clear */ -#define SO_TYPE 0x1008 /* get socket type */ - - -struct in_addr -{ - union - { - struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { unsigned short s_w1,s_w2; } S_un_w; - unsigned long S_addr; - } S_un; -}; -#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ -#define s_host S_un.S_un_b.s_b2 /* host on imp */ -#define s_net S_un.S_un_b.s_b1 /* network */ -#define s_imp S_un.S_un_w.s_w2 /* imp */ -#define s_impno S_un.S_un_b.s_b4 /* imp # */ -#define s_lh S_un.S_un_b.s_b3 /* logical host */ - -struct sockaddr_in -{ - short sin_family; - unsigned short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; - -struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses from name server */ -#define h_addr h_addr_list[0] /* address, for backward compatiblity */ -}; - -char *inet_ntoa(struct in_addr in); - - -// this section is B&W specific constants & structures - -#define BW_IOCTL_BIND 0 -#define BW_IOCTL_CLEAROPTIONS 5 -#define BW_IOCTL_SETOPTIONS 6 -#define BW_IOCTL_PEEK 7 -#define BW_IOCTL_SETWINMASK 8 - -#define BW_OPTION_BLOCKING 0x01 -#define BW_OPTION_REUSEBUFFERS 0x80 - -#define BW_ERR_USR_HANGUP 50 -#define BW_ERR_HANGUP 51 -#define BW_ERR_NET_ERR 52 -#define BW_ERR_IS_CLOSED 53 -#define BW_ERR_TIME_OUT 54 -#define BW_ERR_RESET 55 -#define BW_ERR_FULL 56 -#define BW_ERR_BLOCK 57 -#define BW_ERR_SHUTDOWN 58 - -#pragma pack(1) - -typedef struct -{ - char state; // always 1 - short localPort; - struct in_addr localAddr; - char reason; // always 0 - char options; - short dataAvailable; -} BW_UDPinfo_t; - -typedef struct -{ - char reserved1 [6]; - unsigned short info2Offset; - char reserved2 [18]; - struct in_addr remoteAddr; -} BW_UDPreadInfo1_t; - -typedef struct -{ - short remotePort; - char reserved1 [2]; - unsigned short dataLenPlus8; - char reserved2 [2]; - char data[1]; // actual size is - 8 -} BW_UDPreadInfo2_t; - -typedef struct -{ - char reserved1 [2]; - short remotePort; - unsigned short dataLen; - struct in_addr remoteAddr; - char reserved2 [42]; - char data[1]; // actual size is -} BW_writeInfo_t; - -typedef struct -{ - short ioport; - byte dma; - byte vector; - byte irq; - short bufferSize; - short maxWindow; - short timeZone; - byte myType; - int inetAddr; - short value; - byte subnetMask; - short etherPointer; - short logserverPointer; - short nameserverPointer; - short printserverPointer; - short timeserverPointer; - short gatewayPointer; - short driverSegment; - byte transferSize; - char cardName [9]; -} BW_ethdevinfo_t; - -#pragma pack() - -#define LOWMEM_SIZE 4096 - -static unsigned char *lowmem_buffer; -static int lowmem_bufseg; -static int lowmem_bufoff; -static BW_ethdevinfo_t ethdevinfo; -static int netmask; -static struct in_addr bcastaddr; - -extern regs_t regs; - -static int net_acceptsocket = -1; // socket for fielding new connections -static int net_controlsocket = 0; - -#include "net_bw.h" - -//============================================================================= - -static int BW_ioctl(int s, char *msg, int msglen) -{ - Q_memcpy(lowmem_buffer, msg, msglen); - - regs.x.ax = 0x4403; - regs.x.bx = s; - regs.x.cx = msglen; - regs.x.dx = lowmem_bufoff; - regs.x.ds = lowmem_bufseg; - if (dos_int86(0x21)) - return regs.x.ax; - return 0; -} - -//============================================================================= - -static int BW_TranslateError(int error) -{ - switch(error) - { - case BW_ERR_USR_HANGUP: return ECONNABORTED; - case BW_ERR_HANGUP: return EISCONN; - case BW_ERR_NET_ERR: return ENOTCONN; - case BW_ERR_IS_CLOSED: return ENOTCONN; - case BW_ERR_TIME_OUT: return ETIMEDOUT; - case BW_ERR_RESET: return ECONNREFUSED; - case BW_ERR_FULL: return ETOOMANYREFS; - case BW_ERR_BLOCK: return EWOULDBLOCK; - case BW_ERR_SHUTDOWN: return ESHUTDOWN; - } - return EIO; -} - -//============================================================================= - -static int GetEthdevinfo(void) -{ - int fd; - - Q_strcpy((char *)lowmem_buffer, "ETHDEV27"); - regs.x.ax = 0x3d42; - regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - if (dos_int86(0x21)) - return -1; - fd = regs.x.ax; - - regs.x.ax = 0x4401; - regs.x.bx = fd; - regs.x.dx = 0x60; - dos_int86(0x21); - - regs.h.ah = 0x3f; - regs.x.cx = sizeof(ethdevinfo); - regs.x.es = regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - regs.x.bx = fd; - if (dos_int86(0x21)) - return -1; - Q_memcpy(ðdevinfo, lowmem_buffer, regs.x.ax); - - regs.h.ah = 0x3e; - regs.x.bx = fd; - dos_int86(0x21); - - return 0; -} - -//============================================================================= - -int BW_Init(void) -{ - struct qsockaddr addr; - char *colon; - - if (COM_CheckParm ("-noudp")) - return -1; - - lowmem_buffer = dos_getmemory(LOWMEM_SIZE); - if (!lowmem_buffer) - Sys_Error("not enough low memory\n"); - lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf; - lowmem_bufseg = ptr2real(lowmem_buffer) >> 4; - - if (GetEthdevinfo()) - { - Con_DPrintf("Beame & Whiteside TCP/IP not detected\n"); - dos_freememory(lowmem_buffer); - return -1; - } - netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask); - bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask); - - if ((net_controlsocket = BW_OpenSocket (0)) == -1) - { - dos_freememory(lowmem_buffer); - Con_DPrintf ("BW_Init unable to open control socket; disabled\n"); - return -1; - } - - BW_GetSocketAddr (net_controlsocket, &addr); - Q_strcpy(my_tcpip_address, BW_AddrToString (&addr)); - colon = Q_strrchr (my_tcpip_address, ':'); - if (colon) - *colon = 0; - - Con_Printf("BW_Init: UDP initialized\n"); - tcpipAvailable = true; - - return net_controlsocket; -} - -//============================================================================= - -void BW_Shutdown(void) -{ - BW_Listen (false); - BW_CloseSocket (net_controlsocket); - dos_freememory(lowmem_buffer); -} - -//============================================================================= - -void BW_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1) - Sys_Error ("BW_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - BW_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - - -//============================================================================= - -/* -OpenSocket returns a handle to a network socket that has been opened, -set to nonblocking, and bound to . Additional socket options -should be set here if they are needed. -1 is returned on failure. -*/ - -int BW_OpenSocket(int port) -{ - int s; - int ret; - int deadman = 3 * 1024; - static int dynamic = 1024; - static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS}; - static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0}; - static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING}; - - // allocate a UDP socket - Q_strcpy((char *)lowmem_buffer, "UDP-IP10"); - regs.x.ax = 0x3d42; - regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - if (dos_int86(0x21)) - { - Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax)); - return -1; - } - s = regs.x.ax; - - // set file descriptor to raw mode - regs.x.ax = 0x4401; - regs.x.bx = s; - regs.x.dx = 0x60; - dos_int86(0x21); - - if (BW_ioctl(s, reuse_msg, 2)) - { - Con_Printf("BW_OpenSocket ioctl(reuse) failed\n"); - return -1; - } - - if (BW_ioctl(s, nonblock_msg, 2)) - { - Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n"); - return -1; - } - - // if a socket was specified, bind to it and return - if (port) - { - *(short *)&bind_msg[1] = port; - if (BW_ioctl(s, bind_msg, 3)) - { - BW_CloseSocket(s); - return -1; - } - return s; - } - - // B&W does NOT do dynamic allocation, so if port == 0 we must fake it - do - { - port = dynamic++; - if (dynamic == 4096) - dynamic = 1024; - deadman--; - *(short *)&bind_msg[1] = port; - ret = BW_ioctl(s, bind_msg, 3); - } - while (ret && deadman); - if (ret) - return -1; - return s; -} - -//============================================================================= - -int BW_CloseSocket(int socket) -{ - regs.h.ah = 0x3e; - regs.x.bx = socket; - if(dos_int86(0x21)) - { - Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax)); - return -1; - } - return 0; -} - -//============================================================================= - -int BW_Connect (int socket, struct qsockaddr *hostaddr) -{ - return 0; -} - -//============================================================================= - -int BW_CheckNewConnections(void) -{ - if (net_acceptsocket == 0) - return -1; - - // see if there's anything waiting - regs.x.ax = 0x4406; - regs.x.bx = net_acceptsocket; - dos_int86(0x21); - if (regs.x.ax == 0) - return -1; - return net_acceptsocket; -} - -//============================================================================= - -int BW_Read(int s, byte *buf, int len, struct qsockaddr *from) -{ - BW_UDPreadInfo1_t *info1; - BW_UDPreadInfo2_t *info2; - - // ask if there's anything waiting - regs.x.ax = 0x4406; - regs.x.bx = s; - dos_int86(0x21); - if (regs.x.ax == 0) - return 0; - - // there was, so let's get it - regs.h.ah = 0x3f; - regs.x.cx = /* len + 53 */ LOWMEM_SIZE; - regs.x.es = regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - regs.x.bx = s; - if (dos_int86(0x21)) - { - Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax)); - return -1; - } - - info1 = (BW_UDPreadInfo1_t *)lowmem_buffer; - info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset); - - if (from) - { - from->sa_family = AF_INET; - ((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr; - ((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort); - } - - len = info2->dataLenPlus8 - 8; - if (len > NET_DATAGRAMSIZE) - { - Con_Printf("BW UDP read packet too large: %u\n", len); - return -1; - } - Q_memcpy(buf, info2->data, len); - - return len; -} - -//============================================================================= - -int BW_Broadcast(int s, byte *msg, int len) -{ - BW_writeInfo_t *writeInfo; - - // ask if we're clear to send - regs.x.ax = 0x4407; - regs.x.bx = s; - dos_int86(0x21); - if (regs.x.ax == 0) - return 0; - - // yes, let's do it - writeInfo = (BW_writeInfo_t *)lowmem_buffer; - writeInfo->remoteAddr = bcastaddr; - writeInfo->remotePort = net_hostport; - writeInfo->dataLen = len; - if (len > NET_DATAGRAMSIZE) - Sys_Error("BW UDP write packet too large: %u\n", len); - Q_memcpy(writeInfo->data, msg, len); - writeInfo->data[len] = 0; - regs.h.ah = 0x40; - regs.x.bx = s; - regs.x.cx = len + sizeof(BW_writeInfo_t); - regs.x.es = regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - if (dos_int86(0x21)) - { - Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax)); - return -1; - } - - return len; -} - -//============================================================================= - -int BW_Write(int s, byte *msg, int len, struct qsockaddr *to) -{ - BW_writeInfo_t *writeInfo; - - // ask if we're clear to send - regs.x.ax = 0x4407; - regs.x.bx = s; - dos_int86(0x21); - if (regs.x.ax == 0) - return 0; - - // yes, let's do it - writeInfo = (BW_writeInfo_t *)lowmem_buffer; - writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr; - writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port); - writeInfo->dataLen = len; - if (len > NET_DATAGRAMSIZE) - Sys_Error("BW UDP write packet too large: %u\n", len); - Q_memcpy(writeInfo->data, msg, len); - writeInfo->data[len] = 0; - regs.h.ah = 0x40; - regs.x.bx = s; - regs.x.cx = len + sizeof(BW_writeInfo_t); - regs.x.es = regs.x.ds = lowmem_bufseg; - regs.x.dx = lowmem_bufoff; - if (dos_int86(0x21)) - { - Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax)); - return -1; - } - - return len; -} - -//============================================================================= - - -char *BW_AddrToString (struct qsockaddr *addr) -{ - static char buffer[22]; - - sprintf(buffer, "%d.%d.%d.%d:%d", - ((struct sockaddr_in *)addr)->sin_addr.s_net, - ((struct sockaddr_in *)addr)->sin_addr.s_host, - ((struct sockaddr_in *)addr)->sin_addr.s_lh, - ((struct sockaddr_in *)addr)->sin_addr.s_impno, - ntohs(((struct sockaddr_in *)addr)->sin_port) - ); - return buffer; -} - -//============================================================================= - -int BW_StringToAddr (char *string, struct qsockaddr *addr) -{ - int ha1, ha2, ha3, ha4, hp; - int ipaddr; - - sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); - ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); - ((struct sockaddr_in *)addr)->sin_port = htons((short)hp); - return 0; -} - -//============================================================================= - -int BW_GetSocketAddr (int socket, struct qsockaddr *addr) -{ - regs.x.ax = 0x4402; - regs.x.bx = socket; - regs.x.cx = sizeof(BW_UDPinfo_t); - regs.x.dx = lowmem_bufoff; - regs.x.ds = lowmem_bufseg; - dos_int86(0x21); - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr; - ((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort); - - return 0; -} - -//============================================================================= - -int BW_GetNameFromAddr (struct qsockaddr *addr, char *name) -{ - Q_strcpy(name, BW_AddrToString(addr)); - return 0; -} - -///============================================================================= - -int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr) -{ - char buff[MAXHOSTNAMELEN]; - char *b; - int addr; - int num; - int mask; - int run; - int port; - - if (name[0] < '0' || name[0] > '9') - return -1; - - buff[0] = '.'; - b = buff; - Q_strcpy(buff+1, name); - if (buff[1] == '.') - b++; - - addr = 0; - mask = -1; - while (*b == '.') - { - b++; - num = 0; - run = 0; - while (!( *b < '0' || *b > '9')) - { - num = num*10 + *b++ - '0'; - if (++run > 3) - return -1; - } - if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) - return -1; - if (num < 0 || num > 255) - return -1; - mask<<=8; - addr = (addr<<8) + num; - } - addr = htonl(addr); - mask = htonl(mask); - - if (*b++ == ':') - port = Q_atoi(b); - else - port = net_hostport; - - hostaddr->sa_family = AF_INET; - ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); - ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = - ((ethdevinfo.inetAddr & mask) | addr); - - return 0; -} - -//============================================================================= - -int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) - return 1; - - return 0; -} - -//============================================================================= - -int BW_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_in *)addr)->sin_port); -} - - -int BW_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_in *)addr)->sin_port = htons(port); - return 0; -} - -//============================================================================= +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_bw.c + +#include +#include +#include + +#include "quakedef.h" +#include "dosisms.h" + + +// this section is general Unix stuff that we need + +#define EIO 5 /* I/O error */ +#define EBADS 9 +#define EWOULDBLOCK 35 /* function would block */ +#define EMSGSIZE 40 /* message to big for buffers */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported */ +#define ECONNABORTED 53 /* User requested hangup */ +#define ENOBUFS 55 /* No buffers available */ +#define EISCONN 56 /* Socket has closed */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Socket is closed */ +#define ETOOMANYREFS 59 /* Too many sockets open */ +#define ETIMEDOUT 60 /* Connection timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define AF_INET 2 /* internet */ + +#define PF_INET AF_INET + +#define SOCK_STREAM 1 /* stream */ +#define SOCK_DGRAM 2 /* datagram */ + +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 + +#define INADDR_ANY 0 + +#define SIOCDONE 0x7300 +#define FIONREAD 0x667f +#define FIONBIO 0x667e +#define FIONWIN 0x1000 +#define FIONTIN 0x2000 + +#define BRDINIT 0 +#define BRDADDR 10 + +#define MAXHOSTNAMELEN 256 + +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Option flags per-socket. + */ +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ +#define SO_USEPRIV 0x4000 /* allocate from privileged port area */ +#define SO_CANTSIG 0x8000 /* prevent SIGPIPE on SS_CANTSENDMORE */ + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ + + +struct in_addr +{ + union + { + struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { unsigned short s_w1,s_w2; } S_un_w; + unsigned long S_addr; + } S_un; +}; +#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ +#define s_host S_un.S_un_b.s_b2 /* host on imp */ +#define s_net S_un.S_un_b.s_b1 /* network */ +#define s_imp S_un.S_un_w.s_w2 /* imp */ +#define s_impno S_un.S_un_b.s_b4 /* imp # */ +#define s_lh S_un.S_un_b.s_b3 /* logical host */ + +struct sockaddr_in +{ + short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +#define h_addr h_addr_list[0] /* address, for backward compatiblity */ +}; + +char *inet_ntoa(struct in_addr in); + + +// this section is B&W specific constants & structures + +#define BW_IOCTL_BIND 0 +#define BW_IOCTL_CLEAROPTIONS 5 +#define BW_IOCTL_SETOPTIONS 6 +#define BW_IOCTL_PEEK 7 +#define BW_IOCTL_SETWINMASK 8 + +#define BW_OPTION_BLOCKING 0x01 +#define BW_OPTION_REUSEBUFFERS 0x80 + +#define BW_ERR_USR_HANGUP 50 +#define BW_ERR_HANGUP 51 +#define BW_ERR_NET_ERR 52 +#define BW_ERR_IS_CLOSED 53 +#define BW_ERR_TIME_OUT 54 +#define BW_ERR_RESET 55 +#define BW_ERR_FULL 56 +#define BW_ERR_BLOCK 57 +#define BW_ERR_SHUTDOWN 58 + +#pragma pack(1) + +typedef struct +{ + char state; // always 1 + short localPort; + struct in_addr localAddr; + char reason; // always 0 + char options; + short dataAvailable; +} BW_UDPinfo_t; + +typedef struct +{ + char reserved1 [6]; + unsigned short info2Offset; + char reserved2 [18]; + struct in_addr remoteAddr; +} BW_UDPreadInfo1_t; + +typedef struct +{ + short remotePort; + char reserved1 [2]; + unsigned short dataLenPlus8; + char reserved2 [2]; + char data[1]; // actual size is - 8 +} BW_UDPreadInfo2_t; + +typedef struct +{ + char reserved1 [2]; + short remotePort; + unsigned short dataLen; + struct in_addr remoteAddr; + char reserved2 [42]; + char data[1]; // actual size is +} BW_writeInfo_t; + +typedef struct +{ + short ioport; + byte dma; + byte vector; + byte irq; + short bufferSize; + short maxWindow; + short timeZone; + byte myType; + int inetAddr; + short value; + byte subnetMask; + short etherPointer; + short logserverPointer; + short nameserverPointer; + short printserverPointer; + short timeserverPointer; + short gatewayPointer; + short driverSegment; + byte transferSize; + char cardName [9]; +} BW_ethdevinfo_t; + +#pragma pack() + +#define LOWMEM_SIZE 4096 + +static unsigned char *lowmem_buffer; +static int lowmem_bufseg; +static int lowmem_bufoff; +static BW_ethdevinfo_t ethdevinfo; +static int netmask; +static struct in_addr bcastaddr; + +extern regs_t regs; + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket = 0; + +#include "net_bw.h" + +//============================================================================= + +static int BW_ioctl(int s, char *msg, int msglen) +{ + Q_memcpy(lowmem_buffer, msg, msglen); + + regs.x.ax = 0x4403; + regs.x.bx = s; + regs.x.cx = msglen; + regs.x.dx = lowmem_bufoff; + regs.x.ds = lowmem_bufseg; + if (dos_int86(0x21)) + return regs.x.ax; + return 0; +} + +//============================================================================= + +static int BW_TranslateError(int error) +{ + switch(error) + { + case BW_ERR_USR_HANGUP: return ECONNABORTED; + case BW_ERR_HANGUP: return EISCONN; + case BW_ERR_NET_ERR: return ENOTCONN; + case BW_ERR_IS_CLOSED: return ENOTCONN; + case BW_ERR_TIME_OUT: return ETIMEDOUT; + case BW_ERR_RESET: return ECONNREFUSED; + case BW_ERR_FULL: return ETOOMANYREFS; + case BW_ERR_BLOCK: return EWOULDBLOCK; + case BW_ERR_SHUTDOWN: return ESHUTDOWN; + } + return EIO; +} + +//============================================================================= + +static int GetEthdevinfo(void) +{ + int fd; + + Q_strcpy((char *)lowmem_buffer, "ETHDEV27"); + regs.x.ax = 0x3d42; + regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + if (dos_int86(0x21)) + return -1; + fd = regs.x.ax; + + regs.x.ax = 0x4401; + regs.x.bx = fd; + regs.x.dx = 0x60; + dos_int86(0x21); + + regs.h.ah = 0x3f; + regs.x.cx = sizeof(ethdevinfo); + regs.x.es = regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + regs.x.bx = fd; + if (dos_int86(0x21)) + return -1; + Q_memcpy(ðdevinfo, lowmem_buffer, regs.x.ax); + + regs.h.ah = 0x3e; + regs.x.bx = fd; + dos_int86(0x21); + + return 0; +} + +//============================================================================= + +int BW_Init(void) +{ + struct qsockaddr addr; + char *colon; + + if (COM_CheckParm ("-noudp")) + return -1; + + lowmem_buffer = dos_getmemory(LOWMEM_SIZE); + if (!lowmem_buffer) + Sys_Error("not enough low memory\n"); + lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf; + lowmem_bufseg = ptr2real(lowmem_buffer) >> 4; + + if (GetEthdevinfo()) + { + Con_DPrintf("Beame & Whiteside TCP/IP not detected\n"); + dos_freememory(lowmem_buffer); + return -1; + } + netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask); + bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask); + + if ((net_controlsocket = BW_OpenSocket (0)) == -1) + { + dos_freememory(lowmem_buffer); + Con_DPrintf ("BW_Init unable to open control socket; disabled\n"); + return -1; + } + + BW_GetSocketAddr (net_controlsocket, &addr); + Q_strcpy(my_tcpip_address, BW_AddrToString (&addr)); + colon = Q_strrchr (my_tcpip_address, ':'); + if (colon) + *colon = 0; + + Con_Printf("BW_Init: UDP initialized\n"); + tcpipAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void BW_Shutdown(void) +{ + BW_Listen (false); + BW_CloseSocket (net_controlsocket); + dos_freememory(lowmem_buffer); +} + +//============================================================================= + +void BW_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1) + Sys_Error ("BW_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + BW_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + + +//============================================================================= + +/* +OpenSocket returns a handle to a network socket that has been opened, +set to nonblocking, and bound to . Additional socket options +should be set here if they are needed. -1 is returned on failure. +*/ + +int BW_OpenSocket(int port) +{ + int s; + int ret; + int deadman = 3 * 1024; + static int dynamic = 1024; + static char reuse_msg[2] = {BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS}; + static char bind_msg[3] = {BW_IOCTL_BIND, 0, 0}; + static char nonblock_msg[2] = {BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING}; + + // allocate a UDP socket + Q_strcpy((char *)lowmem_buffer, "UDP-IP10"); + regs.x.ax = 0x3d42; + regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + if (dos_int86(0x21)) + { + Con_Printf("BW_OpenSocket failed: %u\n", BW_TranslateError(regs.x.ax)); + return -1; + } + s = regs.x.ax; + + // set file descriptor to raw mode + regs.x.ax = 0x4401; + regs.x.bx = s; + regs.x.dx = 0x60; + dos_int86(0x21); + + if (BW_ioctl(s, reuse_msg, 2)) + { + Con_Printf("BW_OpenSocket ioctl(reuse) failed\n"); + return -1; + } + + if (BW_ioctl(s, nonblock_msg, 2)) + { + Con_Printf("BW_OpenSocket ioctl(nonblocking) failed\n"); + return -1; + } + + // if a socket was specified, bind to it and return + if (port) + { + *(short *)&bind_msg[1] = port; + if (BW_ioctl(s, bind_msg, 3)) + { + BW_CloseSocket(s); + return -1; + } + return s; + } + + // B&W does NOT do dynamic allocation, so if port == 0 we must fake it + do + { + port = dynamic++; + if (dynamic == 4096) + dynamic = 1024; + deadman--; + *(short *)&bind_msg[1] = port; + ret = BW_ioctl(s, bind_msg, 3); + } + while (ret && deadman); + if (ret) + return -1; + return s; +} + +//============================================================================= + +int BW_CloseSocket(int socket) +{ + regs.h.ah = 0x3e; + regs.x.bx = socket; + if(dos_int86(0x21)) + { + Con_Printf("BW_CloseSocket %u failed: %u\n", socket, BW_TranslateError(regs.x.ax)); + return -1; + } + return 0; +} + +//============================================================================= + +int BW_Connect (int socket, struct qsockaddr *hostaddr) +{ + return 0; +} + +//============================================================================= + +int BW_CheckNewConnections(void) +{ + if (net_acceptsocket == 0) + return -1; + + // see if there's anything waiting + regs.x.ax = 0x4406; + regs.x.bx = net_acceptsocket; + dos_int86(0x21); + if (regs.x.ax == 0) + return -1; + return net_acceptsocket; +} + +//============================================================================= + +int BW_Read(int s, byte *buf, int len, struct qsockaddr *from) +{ + BW_UDPreadInfo1_t *info1; + BW_UDPreadInfo2_t *info2; + + // ask if there's anything waiting + regs.x.ax = 0x4406; + regs.x.bx = s; + dos_int86(0x21); + if (regs.x.ax == 0) + return 0; + + // there was, so let's get it + regs.h.ah = 0x3f; + regs.x.cx = /* len + 53 */ LOWMEM_SIZE; + regs.x.es = regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + regs.x.bx = s; + if (dos_int86(0x21)) + { + Con_Printf("BW UDP read error: %u\n", BW_TranslateError(regs.x.ax)); + return -1; + } + + info1 = (BW_UDPreadInfo1_t *)lowmem_buffer; + info2 = (BW_UDPreadInfo2_t *)(lowmem_buffer + info1->info2Offset); + + if (from) + { + from->sa_family = AF_INET; + ((struct sockaddr_in *)from)->sin_addr = info1->remoteAddr; + ((struct sockaddr_in *)from)->sin_port = htons(info2->remotePort); + } + + len = info2->dataLenPlus8 - 8; + if (len > NET_DATAGRAMSIZE) + { + Con_Printf("BW UDP read packet too large: %u\n", len); + return -1; + } + Q_memcpy(buf, info2->data, len); + + return len; +} + +//============================================================================= + +int BW_Broadcast(int s, byte *msg, int len) +{ + BW_writeInfo_t *writeInfo; + + // ask if we're clear to send + regs.x.ax = 0x4407; + regs.x.bx = s; + dos_int86(0x21); + if (regs.x.ax == 0) + return 0; + + // yes, let's do it + writeInfo = (BW_writeInfo_t *)lowmem_buffer; + writeInfo->remoteAddr = bcastaddr; + writeInfo->remotePort = net_hostport; + writeInfo->dataLen = len; + if (len > NET_DATAGRAMSIZE) + Sys_Error("BW UDP write packet too large: %u\n", len); + Q_memcpy(writeInfo->data, msg, len); + writeInfo->data[len] = 0; + regs.h.ah = 0x40; + regs.x.bx = s; + regs.x.cx = len + sizeof(BW_writeInfo_t); + regs.x.es = regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + if (dos_int86(0x21)) + { + Con_Printf("BW_Broadcast failed: %u\n", BW_TranslateError(regs.x.ax)); + return -1; + } + + return len; +} + +//============================================================================= + +int BW_Write(int s, byte *msg, int len, struct qsockaddr *to) +{ + BW_writeInfo_t *writeInfo; + + // ask if we're clear to send + regs.x.ax = 0x4407; + regs.x.bx = s; + dos_int86(0x21); + if (regs.x.ax == 0) + return 0; + + // yes, let's do it + writeInfo = (BW_writeInfo_t *)lowmem_buffer; + writeInfo->remoteAddr = ((struct sockaddr_in *)to)->sin_addr; + writeInfo->remotePort = ntohs(((struct sockaddr_in *)to)->sin_port); + writeInfo->dataLen = len; + if (len > NET_DATAGRAMSIZE) + Sys_Error("BW UDP write packet too large: %u\n", len); + Q_memcpy(writeInfo->data, msg, len); + writeInfo->data[len] = 0; + regs.h.ah = 0x40; + regs.x.bx = s; + regs.x.cx = len + sizeof(BW_writeInfo_t); + regs.x.es = regs.x.ds = lowmem_bufseg; + regs.x.dx = lowmem_bufoff; + if (dos_int86(0x21)) + { + Con_Printf("BW_Write failed: %u\n", BW_TranslateError(regs.x.ax)); + return -1; + } + + return len; +} + +//============================================================================= + + +char *BW_AddrToString (struct qsockaddr *addr) +{ + static char buffer[22]; + + sprintf(buffer, "%d.%d.%d.%d:%d", + ((struct sockaddr_in *)addr)->sin_addr.s_net, + ((struct sockaddr_in *)addr)->sin_addr.s_host, + ((struct sockaddr_in *)addr)->sin_addr.s_lh, + ((struct sockaddr_in *)addr)->sin_addr.s_impno, + ntohs(((struct sockaddr_in *)addr)->sin_port) + ); + return buffer; +} + +//============================================================================= + +int BW_StringToAddr (char *string, struct qsockaddr *addr) +{ + int ha1, ha2, ha3, ha4, hp; + int ipaddr; + + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); + ((struct sockaddr_in *)addr)->sin_port = htons((short)hp); + return 0; +} + +//============================================================================= + +int BW_GetSocketAddr (int socket, struct qsockaddr *addr) +{ + regs.x.ax = 0x4402; + regs.x.bx = socket; + regs.x.cx = sizeof(BW_UDPinfo_t); + regs.x.dx = lowmem_bufoff; + regs.x.ds = lowmem_bufseg; + dos_int86(0x21); + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = ((BW_UDPinfo_t *)lowmem_buffer)->localAddr.s_addr; + ((struct sockaddr_in *)addr)->sin_port = htons(((BW_UDPinfo_t *)lowmem_buffer)->localPort); + + return 0; +} + +//============================================================================= + +int BW_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + Q_strcpy(name, BW_AddrToString(addr)); + return 0; +} + +///============================================================================= + +int BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr) +{ + char buff[MAXHOSTNAMELEN]; + char *b; + int addr; + int num; + int mask; + int run; + int port; + + if (name[0] < '0' || name[0] > '9') + return -1; + + buff[0] = '.'; + b = buff; + Q_strcpy(buff+1, name); + if (buff[1] == '.') + b++; + + addr = 0; + mask = -1; + while (*b == '.') + { + b++; + num = 0; + run = 0; + while (!( *b < '0' || *b > '9')) + { + num = num*10 + *b++ - '0'; + if (++run > 3) + return -1; + } + if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) + return -1; + if (num < 0 || num > 255) + return -1; + mask<<=8; + addr = (addr<<8) + num; + } + addr = htonl(addr); + mask = htonl(mask); + + if (*b++ == ':') + port = Q_atoi(b); + else + port = net_hostport; + + hostaddr->sa_family = AF_INET; + ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); + ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = + ((ethdevinfo.inetAddr & mask) | addr); + + return 0; +} + +//============================================================================= + +int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) + return 1; + + return 0; +} + +//============================================================================= + +int BW_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_in *)addr)->sin_port); +} + + +int BW_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_in *)addr)->sin_port = htons(port); + return 0; +} + +//============================================================================= diff --git a/WinQuake/net_bw.h b/WinQuake/net_bw.h index 341c49a..7b1b760 100644 --- a/WinQuake/net_bw.h +++ b/WinQuake/net_bw.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_bw.h - -int BW_Init (void); -void BW_Shutdown (void); -void BW_Listen (qboolean state); -int BW_OpenSocket (int port); -int BW_CloseSocket (int socket); -int BW_Connect (int socket, struct qsockaddr *addr); -int BW_CheckNewConnections (void); -int BW_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int BW_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int BW_Broadcast (int socket, byte *buf, int len); -char *BW_AddrToString (struct qsockaddr *addr); -int BW_StringToAddr (char *string, struct qsockaddr *addr); -int BW_GetSocketAddr (int socket, struct qsockaddr *addr); -int BW_GetNameFromAddr (struct qsockaddr *addr, char *name); -int BW_GetAddrFromName (char *name, struct qsockaddr *addr); -int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int BW_GetSocketPort (struct qsockaddr *addr); -int BW_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_bw.h + +int BW_Init (void); +void BW_Shutdown (void); +void BW_Listen (qboolean state); +int BW_OpenSocket (int port); +int BW_CloseSocket (int socket); +int BW_Connect (int socket, struct qsockaddr *addr); +int BW_CheckNewConnections (void); +int BW_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int BW_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int BW_Broadcast (int socket, byte *buf, int len); +char *BW_AddrToString (struct qsockaddr *addr); +int BW_StringToAddr (char *string, struct qsockaddr *addr); +int BW_GetSocketAddr (int socket, struct qsockaddr *addr); +int BW_GetNameFromAddr (struct qsockaddr *addr, char *name); +int BW_GetAddrFromName (char *name, struct qsockaddr *addr); +int BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int BW_GetSocketPort (struct qsockaddr *addr); +int BW_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/net_comx.c b/WinQuake/net_comx.c index 2115a14..77793de 100644 --- a/WinQuake/net_comx.c +++ b/WinQuake/net_comx.c @@ -1,1285 +1,1285 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_comx.c - -#include -#include - -#define NUM_COM_PORTS 2 - -#define ERR_TTY_LINE_STATUS -1 -#define ERR_TTY_MODEM_STATUS -2 -#define ERR_TTY_NODATA -3 - -#define QUEUESIZE 8192 -#define QUEUEMASK (QUEUESIZE - 1) - -typedef struct -{ - volatile int head; - volatile int tail; - volatile byte data[QUEUESIZE]; -} queue; - -#define FULL(q) (q.head == ((q.tail-1) & QUEUEMASK)) -#define EMPTY(q) (q.tail == q.head) -#define ENQUEUE(q,b) (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK) -#define DEQUEUE(q,b) (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK) - -extern cvar_t config_com_port; -extern cvar_t config_com_irq; -extern cvar_t config_com_baud; -extern cvar_t config_com_modem; -extern cvar_t config_modem_dialtype; -extern cvar_t config_modem_clear; -extern cvar_t config_modem_init; -extern cvar_t config_modem_hangup; - -extern int m_return_state; -extern int m_state; -extern qboolean m_return_onerror; -extern char m_return_reason[32]; - -// 8250, 16550 definitions -#define TRANSMIT_HOLDING_REGISTER 0x00 -#define RECEIVE_BUFFER_REGISTER 0x00 -#define INTERRUPT_ENABLE_REGISTER 0x01 -#define IER_RX_DATA_READY 0x01 -#define IER_TX_HOLDING_REGISTER_EMPTY 0x02 -#define IER_LINE_STATUS 0x04 -#define IER_MODEM_STATUS 0x08 -#define INTERRUPT_ID_REGISTER 0x02 -#define IIR_MODEM_STATUS_INTERRUPT 0x00 -#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02 -#define IIR_RX_DATA_READY_INTERRUPT 0x04 -#define IIR_LINE_STATUS_INTERRUPT 0x06 -#define IIR_FIFO_TIMEOUT 0x0c -#define IIR_FIFO_ENABLED 0xc0 -#define FIFO_CONTROL_REGISTER 0x02 -#define FCR_FIFO_ENABLE 0x01 -#define FCR_RCVR_FIFO_RESET 0x02 -#define FCR_XMIT_FIFO_RESET 0x04 -#define FCR_TRIGGER_01 0x00 -#define FCR_TRIGGER_04 0x40 -#define FCR_TRIGGER_08 0x80 -#define FCR_TRIGGER_16 0xc0 -#define LINE_CONTROL_REGISTER 0x03 -#define LCR_DATA_BITS_5 0x00 -#define LCR_DATA_BITS_6 0x01 -#define LCR_DATA_BITS_7 0x02 -#define LCR_DATA_BITS_8 0x03 -#define LCR_STOP_BITS_1 0x00 -#define LCR_STOP_BITS_2 0x04 -#define LCR_PARITY_NONE 0x00 -#define LCR_PARITY_ODD 0x08 -#define LCR_PARITY_EVEN 0x18 -#define LCR_PARITY_MARK 0x28 -#define LCR_PARITY_SPACE 0x38 -#define LCR_SET_BREAK 0x40 -#define LCR_DLAB 0x80 -#define MODEM_CONTROL_REGISTER 0x04 -#define MCR_DTR 0x01 -#define MCR_RTS 0x02 -#define MCR_OUT1 0x04 -#define MCR_OUT2 0x08 -#define MCR_LOOPBACK 0x10 -#define LINE_STATUS_REGISTER 0x05 -#define LSR_DATA_READY 0x01 -#define LSR_OVERRUN_ERROR 0x02 -#define LSR_PARITY_ERROR 0x04 -#define LSR_FRAMING_ERROR 0x08 -#define LSR_BREAK_DETECT 0x10 -#define LSR_TRANSMITTER_BUFFER_EMPTY 0x20 -#define LSR_TRANSMITTER_EMPTY 0x40 -#define LSR_FIFO_DIRTY 0x80 -#define MODEM_STATUS_REGISTER 0x06 -#define MSR_DELTA_CTS 0x01 -#define MSR_DELTA_DSR 0x02 -#define MSR_DELTA_RI 0x04 -#define MSR_DELTA_CD 0x08 -#define MSR_CTS 0x10 -#define MSR_DSR 0x20 -#define MSR_RI 0x40 -#define MSR_CD 0x80 -#define DIVISOR_LATCH_LOW 0x00 -#define DIVISOR_LATCH_HIGH 0x01 - -#define MODEM_STATUS_MASK (MSR_CTS | MSR_DSR | MSR_CD) - -#define UART_AUTO 0 -#define UART_8250 1 -#define UART_16550 2 - -static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8}; -static int ISA_IRQs[] = {4,3,4,3}; - -typedef struct ComPort_s -{ - struct ComPort_s *next; - _go32_dpmi_seginfo protectedModeInfo; - _go32_dpmi_seginfo protectedModeSaveInfo; - int uart; - volatile byte modemStatus; - byte modemStatusIgnore; - byte lineStatus; - byte bufferUsed; - qboolean enabled; - volatile qboolean statusUpdated; - qboolean useModem; - qboolean modemInitialized; - qboolean modemRang; - qboolean modemConnected; - queue inputQueue; - queue outputQueue; - char clear[16]; - char startup[32]; - char shutdown[16]; - char buffer[128]; - PollProcedure poll; - double timestamp; - byte uartType; - byte irq; - byte baudBits; - byte lineControl; - byte portNumber; - char dialType; - char name[4]; -} ComPort; - -ComPort *portList = NULL; -ComPort *handleToPort [NUM_COM_PORTS]; - -static int Modem_Command(ComPort *p, char *commandString); -static char *Modem_Response(ComPort *p); -static void Modem_Hangup(ComPort *p); - -int TTY_Init(void); -void TTY_Shutdown(void); -int TTY_Open(int serialPortNumber); -void TTY_Close(int handle); -int TTY_ReadByte(int handle); -int TTY_WriteByte(int handle, byte data); -void TTY_Flush(int handle); -int TTY_Connect(int handle, char *host); -void TTY_Disconnect(int handle); -qboolean TTY_CheckForConnection(int handle); -qboolean TTY_IsEnabled(int serialPortNumber); -qboolean TTY_IsModem(int serialPortNumber); -qboolean TTY_OutputQueueIsEmpty(int handle); - -static void ISR_8250 (ComPort *p) -{ - byte source = 0; - byte b; - - disable(); - - while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) - { - switch (source) - { - case IIR_RX_DATA_READY_INTERRUPT: - b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); - if (! FULL(p->inputQueue)) - { - ENQUEUE (p->inputQueue, b); - } - else - { - p->lineStatus |= LSR_OVERRUN_ERROR; - p->statusUpdated = true; - } - break; - - case IIR_TX_HOLDING_REGISTER_INTERRUPT: - if (! EMPTY(p->outputQueue)) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - break; - - case IIR_MODEM_STATUS_INTERRUPT: - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->statusUpdated = true; - break; - - case IIR_LINE_STATUS_INTERRUPT: - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - p->statusUpdated = true; - break; - } - source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; - } - outportb (0x20, 0x20); -} - -static void COM1_ISR_8250 (void) -{ - ISR_8250 (handleToPort[0]); -} - -static void COM2_ISR_8250 (void) -{ - ISR_8250 (handleToPort[1]); -} - - - -static void ISR_16550 (ComPort *p) -{ - int count; - byte source; - byte b; - - disable(); - while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) - { - switch (source) - { - case IIR_RX_DATA_READY_INTERRUPT: - do - { - b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); - if (!FULL(p->inputQueue)) - { - ENQUEUE (p->inputQueue, b); - } - else - { - p->lineStatus |= LSR_OVERRUN_ERROR; - p->statusUpdated = true; - } - } while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY); - break; - - case IIR_TX_HOLDING_REGISTER_INTERRUPT: - count = 16; - while ((! EMPTY(p->outputQueue)) && count--) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - break; - - case IIR_MODEM_STATUS_INTERRUPT: - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->statusUpdated = true; - break; - - case IIR_LINE_STATUS_INTERRUPT: - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - p->statusUpdated = true; - break; - } - source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; - } - - // check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a! - if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) - { - count = 16; - while ((! EMPTY(p->outputQueue)) && count--) - { - DEQUEUE (p->outputQueue, b); - outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); - } - } - - outportb (0x20, 0x20); -} - -static void COM1_ISR_16550 (void) -{ - ISR_16550 (handleToPort[0]); -} - -static void COM2_ISR_16550 (void) -{ - ISR_16550 (handleToPort[1]); -} - - -void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem) -{ - ComPort *p; - - p = handleToPort[portNumber]; - *port = p->uart; - *irq = p->irq; - *baud = 115200 / p->baudBits; - *useModem = p->useModem; -} - -void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem) -{ - ComPort *p; - float temp; - - if (useModem) - { - if (baud == 14400) - baud = 19200; - if (baud == 28800) - baud = 38400; - } - - p = handleToPort[portNumber]; - p->uart = port; - p->irq = irq; - p->baudBits = 115200 / baud; - p->useModem = useModem; - - if (useModem) - temp = 1.0; - else - temp = 0.0; - - Cvar_SetValue ("_config_com_port", (float)port); - Cvar_SetValue ("_config_com_irq", (float)irq); - Cvar_SetValue ("_config_com_baud", (float)baud); - Cvar_SetValue ("_config_com_modem", temp); -} - -void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) -{ - ComPort *p; - - p = handleToPort[portNumber]; - *dialType = p->dialType; - Q_strcpy(clear, p->clear); - Q_strcpy(init, p->startup); - Q_strcpy(hangup, p->shutdown); -} - -void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) -{ - ComPort *p; - - p = handleToPort[portNumber]; - p->dialType = dialType[0]; - Q_strcpy(p->clear, clear); - Q_strcpy(p->startup, init); - Q_strcpy(p->shutdown, hangup); - - p->modemInitialized = false; - - Cvar_Set ("_config_modem_dialtype", dialType); - Cvar_Set ("_config_modem_clear", clear); - Cvar_Set ("_config_modem_init", init); - Cvar_Set ("_config_modem_hangup", hangup); -} - - -static void ResetComPortConfig (ComPort *p) -{ - p->useModem = false; - p->uartType = UART_AUTO; - p->uart = ISA_uarts[p->portNumber]; - p->irq = ISA_IRQs[p->portNumber]; - p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR; - p->baudBits = 115200 / 57600; - p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE; - Q_strcpy(p->clear, "ATZ"); - Q_strcpy(p->startup, ""); - Q_strcpy(p->shutdown, "AT H"); - p->modemRang = false; - p->modemConnected = false; - p->statusUpdated = false; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; -} - - -static void ComPort_Enable(ComPort *p) -{ - void (*isr)(void); - int n; - byte b; - - if (p->enabled) - { - Con_Printf("Already enabled\n"); - return; - } - - // disable all UART interrupts - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); - - // clear out any buffered uncoming data - while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY) - inportb (p->uart + RECEIVE_BUFFER_REGISTER); - - // get the current line and modem status - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); - - // clear any UART interrupts - do - { - n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7; - if (n == IIR_RX_DATA_READY_INTERRUPT) - inportb (p->uart + RECEIVE_BUFFER_REGISTER); - } while (!(n & 1)); - - if (p->uartType == UART_AUTO) - { - outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE); - b = inportb (p->uart + INTERRUPT_ID_REGISTER); - if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED) - p->uartType = UART_16550; - else - p->uartType = UART_8250; - } - - // save the old interrupt handler - _go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); - - if (p->uartType == UART_8250) - { - outportb (p->uart + FIFO_CONTROL_REGISTER, 0); - if (p == handleToPort[0]) - isr = COM1_ISR_8250; - else - isr = COM2_ISR_8250; - } - else - { - outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08); - if (p == handleToPort[0]) - isr = COM1_ISR_16550; - else - isr = COM2_ISR_16550; - } - - p->protectedModeInfo.pm_offset = (int)isr; - - n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo); - if (n) - { - Con_Printf("serial: protected mode callback allocation failed\n"); - return; - } - - // disable interrupts at the processor - disable(); - - // install our interrupt handlers now - _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo); - - // enable our interrupt at the PIC - outportb (0x21, inportb (0x21) & ~(1<irq)); - - // enable interrupts at the processor - enable(); - - // enable interrupts at the PIC - outportb (0x20, 0xc2); - - // set baud rate & line control - outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl); - outportb (p->uart, p->baudBits); - outportb (p->uart + 1, 0); - outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl); - - // set modem control register & enable uart interrupt generation - outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); - - // enable the individual interrupts at the uart - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS); - - p->enabled = true; -} - - -static void ComPort_Disable(ComPort *p) -{ - if (!p->enabled) - { - Con_Printf("Already disabled\n"); - return; - } - - // disable interrupts at the uart - outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); - - // disable our interrupt at the PIC - outportb (0x21, inportb (0x21) | (1<irq)); - - // disable interrupts at the processor - disable(); - - // restore the old interrupt handler - _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); - _go32_dpmi_free_iret_wrapper(&p->protectedModeInfo); - - // enable interrupts at the processor - enable(); - - p->enabled = false; -} - - -static int CheckStatus (ComPort *p) -{ - int ret = 0; - - if (p->statusUpdated) - { - p->statusUpdated = false; - - if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT)) - { - if (p->lineStatus & LSR_OVERRUN_ERROR) - Con_DPrintf ("Serial overrun error\n"); - if (p->lineStatus & LSR_PARITY_ERROR) - Con_DPrintf ("Serial parity error\n"); - if (p->lineStatus & LSR_FRAMING_ERROR) - Con_DPrintf ("Serial framing error\n"); - if (p->lineStatus & LSR_BREAK_DETECT) - Con_DPrintf ("Serial break detect\n"); - ret = ERR_TTY_LINE_STATUS; - } - - if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) - { - if (!(p->modemStatus & MSR_CTS)) - Con_Printf ("Serial lost CTS\n"); - if (!(p->modemStatus & MSR_DSR)) - Con_Printf ("Serial lost DSR\n"); - if (!(p->modemStatus & MSR_CD)) - Con_Printf ("Serial lost Carrier\n"); - ret = ERR_TTY_MODEM_STATUS; - } - } - - return ret; -} - - -static void Modem_Init(ComPort *p) -{ - double start; - char *response; - - Con_Printf ("Initializing modem...\n"); - - // write 0 to MCR, wait 1/2 sec, then write the real value back again - // I got this from the guys at head-to-head who say it's necessary. - outportb(p->uart + MODEM_CONTROL_REGISTER, 0); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.5) - ; - outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.25) - ; - - if (*p->clear) - { - Modem_Command (p, p->clear); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 3.0) - { - Con_Printf("No response - clear failed\n"); - p->enabled = false; - goto failed; - } - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "OK", 2) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - { - p->enabled = false; - goto failed; - } - } - } - - if (*p->startup) - { - Modem_Command (p, p->startup); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 3.0) - { - Con_Printf("No response - init failed\n"); - p->enabled = false; - goto failed; - } - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "OK", 2) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - { - p->enabled = false; - goto failed; - } - } - } - - p->modemInitialized = true; - return; - -failed: - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - Q_strcpy(m_return_reason, "Initialization Failed"); - } - return; -} - - -void TTY_Enable(int handle) -{ - ComPort *p; - - p = handleToPort [handle]; - if (p->enabled) - return; - - ComPort_Enable(p); - - if (p->useModem && !p->modemInitialized) - Modem_Init (p); -} - - -int TTY_Open(int serialPortNumber) -{ - return serialPortNumber; -} - - -void TTY_Close(int handle) -{ - ComPort *p; - double startTime; - - p = handleToPort [handle]; - - startTime = Sys_FloatTime(); - while ((Sys_FloatTime() - startTime) < 1.0) - if (EMPTY(p->outputQueue)) - break; - - if (p->useModem) - { - if (p->modemConnected) - Modem_Hangup(p); - } -} - - -int TTY_ReadByte(int handle) -{ - int ret; - ComPort *p; - - p = handleToPort [handle]; - - if ((ret = CheckStatus (p)) != 0) - return ret; - - if (EMPTY (p->inputQueue)) - return ERR_TTY_NODATA; - - DEQUEUE (p->inputQueue, ret); - return (ret & 0xff); -} - - -int TTY_WriteByte(int handle, byte data) -{ - ComPort *p; - - p = handleToPort [handle]; - if (FULL(p->outputQueue)) - return -1; - - ENQUEUE (p->outputQueue, data); - return 0; -} - - -void TTY_Flush(int handle) -{ - byte b; - ComPort *p; - - p = handleToPort [handle]; - - if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) - { - DEQUEUE (p->outputQueue, b); - outportb(p->uart, b); - } -} - - -int TTY_Connect(int handle, char *host) -{ - double start; - ComPort *p; - char *response = NULL; - keydest_t save_key_dest; - byte dialstring[64]; - byte b; - - p = handleToPort[handle]; - - if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) - { - Con_Printf ("Serial: line not ready ("); - if ((p->modemStatus & MSR_CTS) == 0) - Con_Printf(" CTS"); - if ((p->modemStatus & MSR_DSR) == 0) - Con_Printf(" DSR"); - if ((p->modemStatus & MSR_CD) == 0) - Con_Printf(" CD"); - Con_Printf(" )"); - return -1; - } - - // discard any scraps in the input buffer - while (! EMPTY (p->inputQueue)) - DEQUEUE (p->inputQueue, b); - - CheckStatus (p); - - if (p->useModem) - { - save_key_dest = key_dest; - key_dest = key_console; - key_count = -2; - - Con_Printf ("Dialing...\n"); - sprintf(dialstring, "AT D%c %s\r", p->dialType, host); - Modem_Command (p, dialstring); - start = Sys_FloatTime(); - while(1) - { - if ((Sys_FloatTime() - start) > 60.0) - { - Con_Printf("Dialing failure!\n"); - break; - } - - Sys_SendKeyEvents (); - if (key_count == 0) - { - if (key_lastpress != K_ESCAPE) - { - key_count = -2; - continue; - } - Con_Printf("Aborting...\n"); - while ((Sys_FloatTime() - start) < 5.0) - ; - disable(); - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); - enable(); - start = Sys_FloatTime(); - while ((Sys_FloatTime() - start) < 0.75) - ; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); - response = "Aborted"; - break; - } - - response = Modem_Response(p); - if (!response) - continue; - if (Q_strncmp(response, "CONNECT", 7) == 0) - { - disable(); - p->modemRang = true; - p->modemConnected = true; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - key_dest = save_key_dest; - key_count = 0; - m_return_onerror = false; - return 0; - } - if (Q_strncmp(response, "NO CARRIER", 10) == 0) - break; - if (Q_strncmp(response, "NO DIALTONE", 11) == 0) - break; - if (Q_strncmp(response, "NO DIAL TONE", 12) == 0) - break; - if (Q_strncmp(response, "NO ANSWER", 9) == 0) - break; - if (Q_strncmp(response, "BUSY", 4) == 0) - break; - if (Q_strncmp(response, "ERROR", 5) == 0) - break; - } - key_dest = save_key_dest; - key_count = 0; - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - Q_strncpy(m_return_reason, response, 31); - } - return -1; - } - m_return_onerror = false; - return 0; -} - - -void TTY_Disconnect(int handle) -{ - ComPort *p; - - p = handleToPort[handle]; - - if (p->useModem && p->modemConnected) - Modem_Hangup(p); -} - - -qboolean TTY_CheckForConnection(int handle) -{ - ComPort *p; - - p = handleToPort[handle]; - - CheckStatus (p); - - if (p->useModem) - { - if (!p->modemRang) - { - if (!Modem_Response(p)) - return false; - - if (Q_strncmp(p->buffer, "RING", 4) == 0) - { - Modem_Command (p, "ATA"); - p->modemRang = true; - p->timestamp = net_time; - } - return false; - } - if (!p->modemConnected) - { - if ((net_time - p->timestamp) > 35.0) - { - Con_Printf("Unable to establish modem connection\n"); - p->modemRang = false; - return false; - } - - if (!Modem_Response(p)) - return false; - - if (Q_strncmp (p->buffer, "CONNECT", 7) != 0) - return false; - - disable(); - p->modemConnected = true; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - Con_Printf("Modem Connect\n"); - return true; - } - return true; - } - - // direct connect case - if (EMPTY (p->inputQueue)) - return false; - return true; -} - - -qboolean TTY_IsEnabled(int serialPortNumber) -{ - return handleToPort[serialPortNumber]->enabled; -} - - -qboolean TTY_IsModem(int serialPortNumber) -{ - return handleToPort[serialPortNumber]->useModem; -} - - -qboolean TTY_OutputQueueIsEmpty(int handle) -{ - return EMPTY(handleToPort[handle]->outputQueue); -} - - -void Com_f (void) -{ - ComPort *p; - int portNumber; - int i; - int n; - - // first, determine which port they're messing with - portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1; - if (portNumber > 1) - return; - p = handleToPort[portNumber]; - - if (Cmd_Argc() == 1) - { - Con_Printf("Settings for COM%i\n", portNumber + 1); - Con_Printf("enabled: %s\n", p->enabled ? "true" : "false"); - Con_Printf("uart: "); - if (p->uartType == UART_AUTO) - Con_Printf("auto\n"); - else if (p->uartType == UART_8250) - Con_Printf("8250\n"); - else - Con_Printf("16550\n"); - Con_Printf("port: %x\n", p->uart); - Con_Printf("irq: %i\n", p->irq); - Con_Printf("baud: %i\n", 115200 / p->baudBits); - Con_Printf("CTS: %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored"); - Con_Printf("DSR: %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored"); - Con_Printf("CD: %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored"); - if (p->useModem) - { - Con_Printf("type: Modem\n"); - Con_Printf("clear: %s\n", p->clear); - Con_Printf("startup: %s\n", p->startup); - Con_Printf("shutdown: %s\n", p->shutdown); - } - else - Con_Printf("type: Direct connect\n"); - - return; - } - - - if (Cmd_CheckParm ("disable")) - { - if (p->enabled) - ComPort_Disable(p); - p->modemInitialized = false; - return; - } - - if (Cmd_CheckParm ("reset")) - { - ComPort_Disable(p); - ResetComPortConfig (p); - return; - } - - if ((i = Cmd_CheckParm ("port")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change port\n"); - return; - } - p->uart = Q_atoi (Cmd_Argv (i+1)); - } - - if ((i = Cmd_CheckParm ("irq")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change irq\n"); - return; - } - p->irq = Q_atoi (Cmd_Argv (i+1)); - } - - if ((i = Cmd_CheckParm ("baud")) != 0) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change baud\n"); - return; - } - n = Q_atoi (Cmd_Argv (i+1)); - if (n == 0) - Con_Printf("Invalid baud rate specified\n"); - else - p->baudBits = 115200 / n; - } - - if (Cmd_CheckParm ("8250")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_8250; - } - if (Cmd_CheckParm ("16550")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_16550; - } - if (Cmd_CheckParm ("auto")) - { - if (p->enabled) - { - Con_Printf("COM port must be disabled to change uart\n"); - return; - } - p->uartType = UART_AUTO; - } - - if (Cmd_CheckParm ("pulse")) - p->dialType = 'P'; - if (Cmd_CheckParm ("tone")) - p->dialType = 'T'; - - if (Cmd_CheckParm ("direct")) - p->useModem = false; - if (Cmd_CheckParm ("modem")) - p->useModem = true; - - if ((i = Cmd_CheckParm ("clear")) != 0) - { - Q_strncpy (p->clear, Cmd_Argv (i+1), 16); - } - - if ((i = Cmd_CheckParm ("startup")) != 0) - { - Q_strncpy (p->startup, Cmd_Argv (i+1), 32); - p->modemInitialized = false; - } - - if ((i = Cmd_CheckParm ("shutdown")) != 0) - { - Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16); - } - - if (Cmd_CheckParm ("-cts")) - { - p->modemStatusIgnore |= MSR_CTS; - p->modemStatus |= MSR_CTS; - } - - if (Cmd_CheckParm ("+cts")) - { - p->modemStatusIgnore &= (~MSR_CTS); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("-dsr")) - { - p->modemStatusIgnore |= MSR_DSR; - p->modemStatus |= MSR_DSR; - } - - if (Cmd_CheckParm ("+dsr")) - { - p->modemStatusIgnore &= (~MSR_DSR); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("-cd")) - { - p->modemStatusIgnore |= MSR_CD; - p->modemStatus |= MSR_CD; - } - - if (Cmd_CheckParm ("+cd")) - { - p->modemStatusIgnore &= (~MSR_CD); - p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; - } - - if (Cmd_CheckParm ("enable")) - { - if (!p->enabled) - ComPort_Enable(p); - if (p->useModem && !p->modemInitialized) - Modem_Init (p); - } -} - - -int TTY_Init(void) -{ - int n; - ComPort *p; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport"); - if (p == NULL) - Sys_Error("Hunk alloc failed for com port\n"); - p->next = portList; - portList = p; - handleToPort[n] = p; - p->portNumber = n; - p->dialType = 'T'; - sprintf(p->name, "com%u", n+1); - Cmd_AddCommand (p->name, Com_f); - ResetComPortConfig (p); - } - - GetComPortConfig = TTY_GetComPortConfig; - SetComPortConfig = TTY_SetComPortConfig; - GetModemConfig = TTY_GetModemConfig; - SetModemConfig = TTY_SetModemConfig; - - return 0; -} - - -void TTY_Shutdown(void) -{ - int n; - ComPort *p; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - p = handleToPort[n]; - if (p->enabled) - { - while (p->modemConnected) - NET_Poll(); - ComPort_Disable (p); - } - } -} - - -static int Modem_Command(ComPort *p, char *commandString) -{ - byte b; - - if (CheckStatus (p)) - return -1; - - disable(); - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - enable(); - p->bufferUsed = 0; - - while (*commandString) - ENQUEUE (p->outputQueue, *commandString++); - ENQUEUE (p->outputQueue, '\r'); - - // get the transmit rolling - DEQUEUE (p->outputQueue, b); - outportb(p->uart, b); - - return 0; -} - - -static char *Modem_Response(ComPort *p) -{ - byte b; - - if (CheckStatus (p)) - return NULL; - - while (! EMPTY(p->inputQueue)) - { - DEQUEUE (p->inputQueue, b); - - if (p->bufferUsed == (sizeof(p->buffer) - 1)) - b = '\r'; - - if (b == '\r' && p->bufferUsed) - { - p->buffer[p->bufferUsed] = 0; - Con_Printf("%s\n", p->buffer); - SCR_UpdateScreen (); - p->bufferUsed = 0; - return p->buffer; - } - - if (b < ' ' || b > 'z') - continue; - p->buffer[p->bufferUsed] = b; - p->bufferUsed++; - } - - return NULL; -} - - -static void Modem_Hangup2(ComPort *p); -static void Modem_Hangup3(ComPort *p); -static void Modem_Hangup4(ComPort *p); - -static void Modem_Hangup(ComPort *p) -{ - Con_Printf("Hanging up modem...\n"); - disable(); - p->modemRang = false; - p->outputQueue.head = p->outputQueue.tail = 0; - p->inputQueue.head = p->inputQueue.tail = 0; - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); - enable(); - p->poll.procedure = Modem_Hangup2; - p->poll.arg = p; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup2(ComPort *p) -{ - outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); - Modem_Command(p, "+++"); - p->poll.procedure = Modem_Hangup3; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup3(ComPort *p) -{ - Modem_Command(p, p->shutdown); - p->poll.procedure = Modem_Hangup4; - SchedulePollProcedure(&p->poll, 1.5); -} - -static void Modem_Hangup4(ComPort *p) -{ - Modem_Response(p); - Con_Printf("Hangup complete\n"); - p->modemConnected = false; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_comx.c + +#include +#include + +#define NUM_COM_PORTS 2 + +#define ERR_TTY_LINE_STATUS -1 +#define ERR_TTY_MODEM_STATUS -2 +#define ERR_TTY_NODATA -3 + +#define QUEUESIZE 8192 +#define QUEUEMASK (QUEUESIZE - 1) + +typedef struct +{ + volatile int head; + volatile int tail; + volatile byte data[QUEUESIZE]; +} queue; + +#define FULL(q) (q.head == ((q.tail-1) & QUEUEMASK)) +#define EMPTY(q) (q.tail == q.head) +#define ENQUEUE(q,b) (q.data[q.head] = b, q.head = (q.head + 1) & QUEUEMASK) +#define DEQUEUE(q,b) (b = q.data[q.tail], q.tail = (q.tail + 1) & QUEUEMASK) + +extern cvar_t config_com_port; +extern cvar_t config_com_irq; +extern cvar_t config_com_baud; +extern cvar_t config_com_modem; +extern cvar_t config_modem_dialtype; +extern cvar_t config_modem_clear; +extern cvar_t config_modem_init; +extern cvar_t config_modem_hangup; + +extern int m_return_state; +extern int m_state; +extern qboolean m_return_onerror; +extern char m_return_reason[32]; + +// 8250, 16550 definitions +#define TRANSMIT_HOLDING_REGISTER 0x00 +#define RECEIVE_BUFFER_REGISTER 0x00 +#define INTERRUPT_ENABLE_REGISTER 0x01 +#define IER_RX_DATA_READY 0x01 +#define IER_TX_HOLDING_REGISTER_EMPTY 0x02 +#define IER_LINE_STATUS 0x04 +#define IER_MODEM_STATUS 0x08 +#define INTERRUPT_ID_REGISTER 0x02 +#define IIR_MODEM_STATUS_INTERRUPT 0x00 +#define IIR_TX_HOLDING_REGISTER_INTERRUPT 0x02 +#define IIR_RX_DATA_READY_INTERRUPT 0x04 +#define IIR_LINE_STATUS_INTERRUPT 0x06 +#define IIR_FIFO_TIMEOUT 0x0c +#define IIR_FIFO_ENABLED 0xc0 +#define FIFO_CONTROL_REGISTER 0x02 +#define FCR_FIFO_ENABLE 0x01 +#define FCR_RCVR_FIFO_RESET 0x02 +#define FCR_XMIT_FIFO_RESET 0x04 +#define FCR_TRIGGER_01 0x00 +#define FCR_TRIGGER_04 0x40 +#define FCR_TRIGGER_08 0x80 +#define FCR_TRIGGER_16 0xc0 +#define LINE_CONTROL_REGISTER 0x03 +#define LCR_DATA_BITS_5 0x00 +#define LCR_DATA_BITS_6 0x01 +#define LCR_DATA_BITS_7 0x02 +#define LCR_DATA_BITS_8 0x03 +#define LCR_STOP_BITS_1 0x00 +#define LCR_STOP_BITS_2 0x04 +#define LCR_PARITY_NONE 0x00 +#define LCR_PARITY_ODD 0x08 +#define LCR_PARITY_EVEN 0x18 +#define LCR_PARITY_MARK 0x28 +#define LCR_PARITY_SPACE 0x38 +#define LCR_SET_BREAK 0x40 +#define LCR_DLAB 0x80 +#define MODEM_CONTROL_REGISTER 0x04 +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_OUT1 0x04 +#define MCR_OUT2 0x08 +#define MCR_LOOPBACK 0x10 +#define LINE_STATUS_REGISTER 0x05 +#define LSR_DATA_READY 0x01 +#define LSR_OVERRUN_ERROR 0x02 +#define LSR_PARITY_ERROR 0x04 +#define LSR_FRAMING_ERROR 0x08 +#define LSR_BREAK_DETECT 0x10 +#define LSR_TRANSMITTER_BUFFER_EMPTY 0x20 +#define LSR_TRANSMITTER_EMPTY 0x40 +#define LSR_FIFO_DIRTY 0x80 +#define MODEM_STATUS_REGISTER 0x06 +#define MSR_DELTA_CTS 0x01 +#define MSR_DELTA_DSR 0x02 +#define MSR_DELTA_RI 0x04 +#define MSR_DELTA_CD 0x08 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_CD 0x80 +#define DIVISOR_LATCH_LOW 0x00 +#define DIVISOR_LATCH_HIGH 0x01 + +#define MODEM_STATUS_MASK (MSR_CTS | MSR_DSR | MSR_CD) + +#define UART_AUTO 0 +#define UART_8250 1 +#define UART_16550 2 + +static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8}; +static int ISA_IRQs[] = {4,3,4,3}; + +typedef struct ComPort_s +{ + struct ComPort_s *next; + _go32_dpmi_seginfo protectedModeInfo; + _go32_dpmi_seginfo protectedModeSaveInfo; + int uart; + volatile byte modemStatus; + byte modemStatusIgnore; + byte lineStatus; + byte bufferUsed; + qboolean enabled; + volatile qboolean statusUpdated; + qboolean useModem; + qboolean modemInitialized; + qboolean modemRang; + qboolean modemConnected; + queue inputQueue; + queue outputQueue; + char clear[16]; + char startup[32]; + char shutdown[16]; + char buffer[128]; + PollProcedure poll; + double timestamp; + byte uartType; + byte irq; + byte baudBits; + byte lineControl; + byte portNumber; + char dialType; + char name[4]; +} ComPort; + +ComPort *portList = NULL; +ComPort *handleToPort [NUM_COM_PORTS]; + +static int Modem_Command(ComPort *p, char *commandString); +static char *Modem_Response(ComPort *p); +static void Modem_Hangup(ComPort *p); + +int TTY_Init(void); +void TTY_Shutdown(void); +int TTY_Open(int serialPortNumber); +void TTY_Close(int handle); +int TTY_ReadByte(int handle); +int TTY_WriteByte(int handle, byte data); +void TTY_Flush(int handle); +int TTY_Connect(int handle, char *host); +void TTY_Disconnect(int handle); +qboolean TTY_CheckForConnection(int handle); +qboolean TTY_IsEnabled(int serialPortNumber); +qboolean TTY_IsModem(int serialPortNumber); +qboolean TTY_OutputQueueIsEmpty(int handle); + +static void ISR_8250 (ComPort *p) +{ + byte source = 0; + byte b; + + disable(); + + while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) + { + switch (source) + { + case IIR_RX_DATA_READY_INTERRUPT: + b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); + if (! FULL(p->inputQueue)) + { + ENQUEUE (p->inputQueue, b); + } + else + { + p->lineStatus |= LSR_OVERRUN_ERROR; + p->statusUpdated = true; + } + break; + + case IIR_TX_HOLDING_REGISTER_INTERRUPT: + if (! EMPTY(p->outputQueue)) + { + DEQUEUE (p->outputQueue, b); + outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); + } + break; + + case IIR_MODEM_STATUS_INTERRUPT: + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + p->statusUpdated = true; + break; + + case IIR_LINE_STATUS_INTERRUPT: + p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); + p->statusUpdated = true; + break; + } + source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; + } + outportb (0x20, 0x20); +} + +static void COM1_ISR_8250 (void) +{ + ISR_8250 (handleToPort[0]); +} + +static void COM2_ISR_8250 (void) +{ + ISR_8250 (handleToPort[1]); +} + + + +static void ISR_16550 (ComPort *p) +{ + int count; + byte source; + byte b; + + disable(); + while((source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07) != 1) + { + switch (source) + { + case IIR_RX_DATA_READY_INTERRUPT: + do + { + b = inportb (p->uart + RECEIVE_BUFFER_REGISTER); + if (!FULL(p->inputQueue)) + { + ENQUEUE (p->inputQueue, b); + } + else + { + p->lineStatus |= LSR_OVERRUN_ERROR; + p->statusUpdated = true; + } + } while (inportb (p->uart + LINE_STATUS_REGISTER) & LSR_DATA_READY); + break; + + case IIR_TX_HOLDING_REGISTER_INTERRUPT: + count = 16; + while ((! EMPTY(p->outputQueue)) && count--) + { + DEQUEUE (p->outputQueue, b); + outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); + } + break; + + case IIR_MODEM_STATUS_INTERRUPT: + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + p->statusUpdated = true; + break; + + case IIR_LINE_STATUS_INTERRUPT: + p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); + p->statusUpdated = true; + break; + } + source = inportb (p->uart + INTERRUPT_ID_REGISTER) & 0x07; + } + + // check for lost IIR_TX_HOLDING_REGISTER_INTERRUPT on 16550a! + if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) + { + count = 16; + while ((! EMPTY(p->outputQueue)) && count--) + { + DEQUEUE (p->outputQueue, b); + outportb (p->uart + TRANSMIT_HOLDING_REGISTER, b); + } + } + + outportb (0x20, 0x20); +} + +static void COM1_ISR_16550 (void) +{ + ISR_16550 (handleToPort[0]); +} + +static void COM2_ISR_16550 (void) +{ + ISR_16550 (handleToPort[1]); +} + + +void TTY_GetComPortConfig (int portNumber, int *port, int *irq, int *baud, qboolean *useModem) +{ + ComPort *p; + + p = handleToPort[portNumber]; + *port = p->uart; + *irq = p->irq; + *baud = 115200 / p->baudBits; + *useModem = p->useModem; +} + +void TTY_SetComPortConfig (int portNumber, int port, int irq, int baud, qboolean useModem) +{ + ComPort *p; + float temp; + + if (useModem) + { + if (baud == 14400) + baud = 19200; + if (baud == 28800) + baud = 38400; + } + + p = handleToPort[portNumber]; + p->uart = port; + p->irq = irq; + p->baudBits = 115200 / baud; + p->useModem = useModem; + + if (useModem) + temp = 1.0; + else + temp = 0.0; + + Cvar_SetValue ("_config_com_port", (float)port); + Cvar_SetValue ("_config_com_irq", (float)irq); + Cvar_SetValue ("_config_com_baud", (float)baud); + Cvar_SetValue ("_config_com_modem", temp); +} + +void TTY_GetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) +{ + ComPort *p; + + p = handleToPort[portNumber]; + *dialType = p->dialType; + Q_strcpy(clear, p->clear); + Q_strcpy(init, p->startup); + Q_strcpy(hangup, p->shutdown); +} + +void TTY_SetModemConfig (int portNumber, char *dialType, char *clear, char *init, char *hangup) +{ + ComPort *p; + + p = handleToPort[portNumber]; + p->dialType = dialType[0]; + Q_strcpy(p->clear, clear); + Q_strcpy(p->startup, init); + Q_strcpy(p->shutdown, hangup); + + p->modemInitialized = false; + + Cvar_Set ("_config_modem_dialtype", dialType); + Cvar_Set ("_config_modem_clear", clear); + Cvar_Set ("_config_modem_init", init); + Cvar_Set ("_config_modem_hangup", hangup); +} + + +static void ResetComPortConfig (ComPort *p) +{ + p->useModem = false; + p->uartType = UART_AUTO; + p->uart = ISA_uarts[p->portNumber]; + p->irq = ISA_IRQs[p->portNumber]; + p->modemStatusIgnore = MSR_CD | MSR_CTS | MSR_DSR; + p->baudBits = 115200 / 57600; + p->lineControl = LCR_DATA_BITS_8 | LCR_STOP_BITS_1 | LCR_PARITY_NONE; + Q_strcpy(p->clear, "ATZ"); + Q_strcpy(p->startup, ""); + Q_strcpy(p->shutdown, "AT H"); + p->modemRang = false; + p->modemConnected = false; + p->statusUpdated = false; + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; +} + + +static void ComPort_Enable(ComPort *p) +{ + void (*isr)(void); + int n; + byte b; + + if (p->enabled) + { + Con_Printf("Already enabled\n"); + return; + } + + // disable all UART interrupts + outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); + + // clear out any buffered uncoming data + while((inportb (p->uart + LINE_STATUS_REGISTER)) & LSR_DATA_READY) + inportb (p->uart + RECEIVE_BUFFER_REGISTER); + + // get the current line and modem status + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + p->lineStatus = inportb (p->uart + LINE_STATUS_REGISTER); + + // clear any UART interrupts + do + { + n = inportb (p->uart + INTERRUPT_ID_REGISTER) & 7; + if (n == IIR_RX_DATA_READY_INTERRUPT) + inportb (p->uart + RECEIVE_BUFFER_REGISTER); + } while (!(n & 1)); + + if (p->uartType == UART_AUTO) + { + outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE); + b = inportb (p->uart + INTERRUPT_ID_REGISTER); + if ((b & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED) + p->uartType = UART_16550; + else + p->uartType = UART_8250; + } + + // save the old interrupt handler + _go32_dpmi_get_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); + + if (p->uartType == UART_8250) + { + outportb (p->uart + FIFO_CONTROL_REGISTER, 0); + if (p == handleToPort[0]) + isr = COM1_ISR_8250; + else + isr = COM2_ISR_8250; + } + else + { + outportb (p->uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE | FCR_RCVR_FIFO_RESET | FCR_XMIT_FIFO_RESET | FCR_TRIGGER_08); + if (p == handleToPort[0]) + isr = COM1_ISR_16550; + else + isr = COM2_ISR_16550; + } + + p->protectedModeInfo.pm_offset = (int)isr; + + n = _go32_dpmi_allocate_iret_wrapper(&p->protectedModeInfo); + if (n) + { + Con_Printf("serial: protected mode callback allocation failed\n"); + return; + } + + // disable interrupts at the processor + disable(); + + // install our interrupt handlers now + _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeInfo); + + // enable our interrupt at the PIC + outportb (0x21, inportb (0x21) & ~(1<irq)); + + // enable interrupts at the processor + enable(); + + // enable interrupts at the PIC + outportb (0x20, 0xc2); + + // set baud rate & line control + outportb (p->uart + LINE_CONTROL_REGISTER, LCR_DLAB | p->lineControl); + outportb (p->uart, p->baudBits); + outportb (p->uart + 1, 0); + outportb (p->uart + LINE_CONTROL_REGISTER, p->lineControl); + + // set modem control register & enable uart interrupt generation + outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); + + // enable the individual interrupts at the uart + outportb (p->uart + INTERRUPT_ENABLE_REGISTER, IER_RX_DATA_READY | IER_TX_HOLDING_REGISTER_EMPTY | IER_LINE_STATUS | IER_MODEM_STATUS); + + p->enabled = true; +} + + +static void ComPort_Disable(ComPort *p) +{ + if (!p->enabled) + { + Con_Printf("Already disabled\n"); + return; + } + + // disable interrupts at the uart + outportb (p->uart + INTERRUPT_ENABLE_REGISTER, 0); + + // disable our interrupt at the PIC + outportb (0x21, inportb (0x21) | (1<irq)); + + // disable interrupts at the processor + disable(); + + // restore the old interrupt handler + _go32_dpmi_set_protected_mode_interrupt_vector(p->irq + 8, &p->protectedModeSaveInfo); + _go32_dpmi_free_iret_wrapper(&p->protectedModeInfo); + + // enable interrupts at the processor + enable(); + + p->enabled = false; +} + + +static int CheckStatus (ComPort *p) +{ + int ret = 0; + + if (p->statusUpdated) + { + p->statusUpdated = false; + + if (p->lineStatus & (LSR_OVERRUN_ERROR | LSR_PARITY_ERROR | LSR_FRAMING_ERROR | LSR_BREAK_DETECT)) + { + if (p->lineStatus & LSR_OVERRUN_ERROR) + Con_DPrintf ("Serial overrun error\n"); + if (p->lineStatus & LSR_PARITY_ERROR) + Con_DPrintf ("Serial parity error\n"); + if (p->lineStatus & LSR_FRAMING_ERROR) + Con_DPrintf ("Serial framing error\n"); + if (p->lineStatus & LSR_BREAK_DETECT) + Con_DPrintf ("Serial break detect\n"); + ret = ERR_TTY_LINE_STATUS; + } + + if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) + { + if (!(p->modemStatus & MSR_CTS)) + Con_Printf ("Serial lost CTS\n"); + if (!(p->modemStatus & MSR_DSR)) + Con_Printf ("Serial lost DSR\n"); + if (!(p->modemStatus & MSR_CD)) + Con_Printf ("Serial lost Carrier\n"); + ret = ERR_TTY_MODEM_STATUS; + } + } + + return ret; +} + + +static void Modem_Init(ComPort *p) +{ + double start; + char *response; + + Con_Printf ("Initializing modem...\n"); + + // write 0 to MCR, wait 1/2 sec, then write the real value back again + // I got this from the guys at head-to-head who say it's necessary. + outportb(p->uart + MODEM_CONTROL_REGISTER, 0); + start = Sys_FloatTime(); + while ((Sys_FloatTime() - start) < 0.5) + ; + outportb(p->uart + MODEM_CONTROL_REGISTER, MCR_OUT2 | MCR_RTS | MCR_DTR); + start = Sys_FloatTime(); + while ((Sys_FloatTime() - start) < 0.25) + ; + + if (*p->clear) + { + Modem_Command (p, p->clear); + start = Sys_FloatTime(); + while(1) + { + if ((Sys_FloatTime() - start) > 3.0) + { + Con_Printf("No response - clear failed\n"); + p->enabled = false; + goto failed; + } + response = Modem_Response(p); + if (!response) + continue; + if (Q_strncmp(response, "OK", 2) == 0) + break; + if (Q_strncmp(response, "ERROR", 5) == 0) + { + p->enabled = false; + goto failed; + } + } + } + + if (*p->startup) + { + Modem_Command (p, p->startup); + start = Sys_FloatTime(); + while(1) + { + if ((Sys_FloatTime() - start) > 3.0) + { + Con_Printf("No response - init failed\n"); + p->enabled = false; + goto failed; + } + response = Modem_Response(p); + if (!response) + continue; + if (Q_strncmp(response, "OK", 2) == 0) + break; + if (Q_strncmp(response, "ERROR", 5) == 0) + { + p->enabled = false; + goto failed; + } + } + } + + p->modemInitialized = true; + return; + +failed: + if (m_return_onerror) + { + key_dest = key_menu; + m_state = m_return_state; + m_return_onerror = false; + Q_strcpy(m_return_reason, "Initialization Failed"); + } + return; +} + + +void TTY_Enable(int handle) +{ + ComPort *p; + + p = handleToPort [handle]; + if (p->enabled) + return; + + ComPort_Enable(p); + + if (p->useModem && !p->modemInitialized) + Modem_Init (p); +} + + +int TTY_Open(int serialPortNumber) +{ + return serialPortNumber; +} + + +void TTY_Close(int handle) +{ + ComPort *p; + double startTime; + + p = handleToPort [handle]; + + startTime = Sys_FloatTime(); + while ((Sys_FloatTime() - startTime) < 1.0) + if (EMPTY(p->outputQueue)) + break; + + if (p->useModem) + { + if (p->modemConnected) + Modem_Hangup(p); + } +} + + +int TTY_ReadByte(int handle) +{ + int ret; + ComPort *p; + + p = handleToPort [handle]; + + if ((ret = CheckStatus (p)) != 0) + return ret; + + if (EMPTY (p->inputQueue)) + return ERR_TTY_NODATA; + + DEQUEUE (p->inputQueue, ret); + return (ret & 0xff); +} + + +int TTY_WriteByte(int handle, byte data) +{ + ComPort *p; + + p = handleToPort [handle]; + if (FULL(p->outputQueue)) + return -1; + + ENQUEUE (p->outputQueue, data); + return 0; +} + + +void TTY_Flush(int handle) +{ + byte b; + ComPort *p; + + p = handleToPort [handle]; + + if (inportb (p->uart + LINE_STATUS_REGISTER ) & LSR_TRANSMITTER_EMPTY) + { + DEQUEUE (p->outputQueue, b); + outportb(p->uart, b); + } +} + + +int TTY_Connect(int handle, char *host) +{ + double start; + ComPort *p; + char *response = NULL; + keydest_t save_key_dest; + byte dialstring[64]; + byte b; + + p = handleToPort[handle]; + + if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) + { + Con_Printf ("Serial: line not ready ("); + if ((p->modemStatus & MSR_CTS) == 0) + Con_Printf(" CTS"); + if ((p->modemStatus & MSR_DSR) == 0) + Con_Printf(" DSR"); + if ((p->modemStatus & MSR_CD) == 0) + Con_Printf(" CD"); + Con_Printf(" )"); + return -1; + } + + // discard any scraps in the input buffer + while (! EMPTY (p->inputQueue)) + DEQUEUE (p->inputQueue, b); + + CheckStatus (p); + + if (p->useModem) + { + save_key_dest = key_dest; + key_dest = key_console; + key_count = -2; + + Con_Printf ("Dialing...\n"); + sprintf(dialstring, "AT D%c %s\r", p->dialType, host); + Modem_Command (p, dialstring); + start = Sys_FloatTime(); + while(1) + { + if ((Sys_FloatTime() - start) > 60.0) + { + Con_Printf("Dialing failure!\n"); + break; + } + + Sys_SendKeyEvents (); + if (key_count == 0) + { + if (key_lastpress != K_ESCAPE) + { + key_count = -2; + continue; + } + Con_Printf("Aborting...\n"); + while ((Sys_FloatTime() - start) < 5.0) + ; + disable(); + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; + outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); + enable(); + start = Sys_FloatTime(); + while ((Sys_FloatTime() - start) < 0.75) + ; + outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); + response = "Aborted"; + break; + } + + response = Modem_Response(p); + if (!response) + continue; + if (Q_strncmp(response, "CONNECT", 7) == 0) + { + disable(); + p->modemRang = true; + p->modemConnected = true; + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; + enable(); + key_dest = save_key_dest; + key_count = 0; + m_return_onerror = false; + return 0; + } + if (Q_strncmp(response, "NO CARRIER", 10) == 0) + break; + if (Q_strncmp(response, "NO DIALTONE", 11) == 0) + break; + if (Q_strncmp(response, "NO DIAL TONE", 12) == 0) + break; + if (Q_strncmp(response, "NO ANSWER", 9) == 0) + break; + if (Q_strncmp(response, "BUSY", 4) == 0) + break; + if (Q_strncmp(response, "ERROR", 5) == 0) + break; + } + key_dest = save_key_dest; + key_count = 0; + if (m_return_onerror) + { + key_dest = key_menu; + m_state = m_return_state; + m_return_onerror = false; + Q_strncpy(m_return_reason, response, 31); + } + return -1; + } + m_return_onerror = false; + return 0; +} + + +void TTY_Disconnect(int handle) +{ + ComPort *p; + + p = handleToPort[handle]; + + if (p->useModem && p->modemConnected) + Modem_Hangup(p); +} + + +qboolean TTY_CheckForConnection(int handle) +{ + ComPort *p; + + p = handleToPort[handle]; + + CheckStatus (p); + + if (p->useModem) + { + if (!p->modemRang) + { + if (!Modem_Response(p)) + return false; + + if (Q_strncmp(p->buffer, "RING", 4) == 0) + { + Modem_Command (p, "ATA"); + p->modemRang = true; + p->timestamp = net_time; + } + return false; + } + if (!p->modemConnected) + { + if ((net_time - p->timestamp) > 35.0) + { + Con_Printf("Unable to establish modem connection\n"); + p->modemRang = false; + return false; + } + + if (!Modem_Response(p)) + return false; + + if (Q_strncmp (p->buffer, "CONNECT", 7) != 0) + return false; + + disable(); + p->modemConnected = true; + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; + enable(); + Con_Printf("Modem Connect\n"); + return true; + } + return true; + } + + // direct connect case + if (EMPTY (p->inputQueue)) + return false; + return true; +} + + +qboolean TTY_IsEnabled(int serialPortNumber) +{ + return handleToPort[serialPortNumber]->enabled; +} + + +qboolean TTY_IsModem(int serialPortNumber) +{ + return handleToPort[serialPortNumber]->useModem; +} + + +qboolean TTY_OutputQueueIsEmpty(int handle) +{ + return EMPTY(handleToPort[handle]->outputQueue); +} + + +void Com_f (void) +{ + ComPort *p; + int portNumber; + int i; + int n; + + // first, determine which port they're messing with + portNumber = Q_atoi(Cmd_Argv (0) + 3) - 1; + if (portNumber > 1) + return; + p = handleToPort[portNumber]; + + if (Cmd_Argc() == 1) + { + Con_Printf("Settings for COM%i\n", portNumber + 1); + Con_Printf("enabled: %s\n", p->enabled ? "true" : "false"); + Con_Printf("uart: "); + if (p->uartType == UART_AUTO) + Con_Printf("auto\n"); + else if (p->uartType == UART_8250) + Con_Printf("8250\n"); + else + Con_Printf("16550\n"); + Con_Printf("port: %x\n", p->uart); + Con_Printf("irq: %i\n", p->irq); + Con_Printf("baud: %i\n", 115200 / p->baudBits); + Con_Printf("CTS: %s\n", (p->modemStatusIgnore & MSR_CTS) ? "ignored" : "honored"); + Con_Printf("DSR: %s\n", (p->modemStatusIgnore & MSR_DSR) ? "ignored" : "honored"); + Con_Printf("CD: %s\n", (p->modemStatusIgnore & MSR_CD) ? "ignored" : "honored"); + if (p->useModem) + { + Con_Printf("type: Modem\n"); + Con_Printf("clear: %s\n", p->clear); + Con_Printf("startup: %s\n", p->startup); + Con_Printf("shutdown: %s\n", p->shutdown); + } + else + Con_Printf("type: Direct connect\n"); + + return; + } + + + if (Cmd_CheckParm ("disable")) + { + if (p->enabled) + ComPort_Disable(p); + p->modemInitialized = false; + return; + } + + if (Cmd_CheckParm ("reset")) + { + ComPort_Disable(p); + ResetComPortConfig (p); + return; + } + + if ((i = Cmd_CheckParm ("port")) != 0) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change port\n"); + return; + } + p->uart = Q_atoi (Cmd_Argv (i+1)); + } + + if ((i = Cmd_CheckParm ("irq")) != 0) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change irq\n"); + return; + } + p->irq = Q_atoi (Cmd_Argv (i+1)); + } + + if ((i = Cmd_CheckParm ("baud")) != 0) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change baud\n"); + return; + } + n = Q_atoi (Cmd_Argv (i+1)); + if (n == 0) + Con_Printf("Invalid baud rate specified\n"); + else + p->baudBits = 115200 / n; + } + + if (Cmd_CheckParm ("8250")) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change uart\n"); + return; + } + p->uartType = UART_8250; + } + if (Cmd_CheckParm ("16550")) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change uart\n"); + return; + } + p->uartType = UART_16550; + } + if (Cmd_CheckParm ("auto")) + { + if (p->enabled) + { + Con_Printf("COM port must be disabled to change uart\n"); + return; + } + p->uartType = UART_AUTO; + } + + if (Cmd_CheckParm ("pulse")) + p->dialType = 'P'; + if (Cmd_CheckParm ("tone")) + p->dialType = 'T'; + + if (Cmd_CheckParm ("direct")) + p->useModem = false; + if (Cmd_CheckParm ("modem")) + p->useModem = true; + + if ((i = Cmd_CheckParm ("clear")) != 0) + { + Q_strncpy (p->clear, Cmd_Argv (i+1), 16); + } + + if ((i = Cmd_CheckParm ("startup")) != 0) + { + Q_strncpy (p->startup, Cmd_Argv (i+1), 32); + p->modemInitialized = false; + } + + if ((i = Cmd_CheckParm ("shutdown")) != 0) + { + Q_strncpy (p->shutdown, Cmd_Argv (i+1), 16); + } + + if (Cmd_CheckParm ("-cts")) + { + p->modemStatusIgnore |= MSR_CTS; + p->modemStatus |= MSR_CTS; + } + + if (Cmd_CheckParm ("+cts")) + { + p->modemStatusIgnore &= (~MSR_CTS); + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + } + + if (Cmd_CheckParm ("-dsr")) + { + p->modemStatusIgnore |= MSR_DSR; + p->modemStatus |= MSR_DSR; + } + + if (Cmd_CheckParm ("+dsr")) + { + p->modemStatusIgnore &= (~MSR_DSR); + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + } + + if (Cmd_CheckParm ("-cd")) + { + p->modemStatusIgnore |= MSR_CD; + p->modemStatus |= MSR_CD; + } + + if (Cmd_CheckParm ("+cd")) + { + p->modemStatusIgnore &= (~MSR_CD); + p->modemStatus = (inportb (p->uart + MODEM_STATUS_REGISTER) & MODEM_STATUS_MASK) | p->modemStatusIgnore; + } + + if (Cmd_CheckParm ("enable")) + { + if (!p->enabled) + ComPort_Enable(p); + if (p->useModem && !p->modemInitialized) + Modem_Init (p); + } +} + + +int TTY_Init(void) +{ + int n; + ComPort *p; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + p = (ComPort *)Hunk_AllocName(sizeof(ComPort), "comport"); + if (p == NULL) + Sys_Error("Hunk alloc failed for com port\n"); + p->next = portList; + portList = p; + handleToPort[n] = p; + p->portNumber = n; + p->dialType = 'T'; + sprintf(p->name, "com%u", n+1); + Cmd_AddCommand (p->name, Com_f); + ResetComPortConfig (p); + } + + GetComPortConfig = TTY_GetComPortConfig; + SetComPortConfig = TTY_SetComPortConfig; + GetModemConfig = TTY_GetModemConfig; + SetModemConfig = TTY_SetModemConfig; + + return 0; +} + + +void TTY_Shutdown(void) +{ + int n; + ComPort *p; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + p = handleToPort[n]; + if (p->enabled) + { + while (p->modemConnected) + NET_Poll(); + ComPort_Disable (p); + } + } +} + + +static int Modem_Command(ComPort *p, char *commandString) +{ + byte b; + + if (CheckStatus (p)) + return -1; + + disable(); + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; + enable(); + p->bufferUsed = 0; + + while (*commandString) + ENQUEUE (p->outputQueue, *commandString++); + ENQUEUE (p->outputQueue, '\r'); + + // get the transmit rolling + DEQUEUE (p->outputQueue, b); + outportb(p->uart, b); + + return 0; +} + + +static char *Modem_Response(ComPort *p) +{ + byte b; + + if (CheckStatus (p)) + return NULL; + + while (! EMPTY(p->inputQueue)) + { + DEQUEUE (p->inputQueue, b); + + if (p->bufferUsed == (sizeof(p->buffer) - 1)) + b = '\r'; + + if (b == '\r' && p->bufferUsed) + { + p->buffer[p->bufferUsed] = 0; + Con_Printf("%s\n", p->buffer); + SCR_UpdateScreen (); + p->bufferUsed = 0; + return p->buffer; + } + + if (b < ' ' || b > 'z') + continue; + p->buffer[p->bufferUsed] = b; + p->bufferUsed++; + } + + return NULL; +} + + +static void Modem_Hangup2(ComPort *p); +static void Modem_Hangup3(ComPort *p); +static void Modem_Hangup4(ComPort *p); + +static void Modem_Hangup(ComPort *p) +{ + Con_Printf("Hanging up modem...\n"); + disable(); + p->modemRang = false; + p->outputQueue.head = p->outputQueue.tail = 0; + p->inputQueue.head = p->inputQueue.tail = 0; + outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); + enable(); + p->poll.procedure = Modem_Hangup2; + p->poll.arg = p; + SchedulePollProcedure(&p->poll, 1.5); +} + +static void Modem_Hangup2(ComPort *p) +{ + outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); + Modem_Command(p, "+++"); + p->poll.procedure = Modem_Hangup3; + SchedulePollProcedure(&p->poll, 1.5); +} + +static void Modem_Hangup3(ComPort *p) +{ + Modem_Command(p, p->shutdown); + p->poll.procedure = Modem_Hangup4; + SchedulePollProcedure(&p->poll, 1.5); +} + +static void Modem_Hangup4(ComPort *p) +{ + Modem_Response(p); + Con_Printf("Hangup complete\n"); + p->modemConnected = false; +} diff --git a/WinQuake/net_dgrm.c b/WinQuake/net_dgrm.c index a293b77..a08b3d3 100644 --- a/WinQuake/net_dgrm.c +++ b/WinQuake/net_dgrm.c @@ -1,1390 +1,1390 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_dgrm.c - -// This is enables a simple IP banning mechanism -#define BAN_TEST - -#ifdef BAN_TEST -#if defined(_WIN32) -#include -#elif defined (NeXT) -#include -#include -#else -#define AF_INET 2 /* internet */ -struct in_addr -{ - union - { - struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { unsigned short s_w1,s_w2; } S_un_w; - unsigned long S_addr; - } S_un; -}; -#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ -struct sockaddr_in -{ - short sin_family; - unsigned short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; -char *inet_ntoa(struct in_addr in); -unsigned long inet_addr(const char *cp); -#endif -#endif // BAN_TEST - -#include "quakedef.h" -#include "net_dgrm.h" - -// these two macros are to make the code more readable -#define sfunc net_landrivers[sock->landriver] -#define dfunc net_landrivers[net_landriverlevel] - -static int net_landriverlevel; - -/* statistic counters */ -int packetsSent = 0; -int packetsReSent = 0; -int packetsReceived = 0; -int receivedDuplicateCount = 0; -int shortPacketCount = 0; -int droppedDatagrams; - -static int myDriverLevel; - -struct -{ - unsigned int length; - unsigned int sequence; - byte data[MAX_DATAGRAM]; -} packetBuffer; - -extern int m_return_state; -extern int m_state; -extern qboolean m_return_onerror; -extern char m_return_reason[32]; - - -#ifdef DEBUG -char *StrAddr (struct qsockaddr *addr) -{ - static char buf[34]; - byte *p = (byte *)addr; - int n; - - for (n = 0; n < 16; n++) - sprintf (buf + n * 2, "%02x", *p++); - return buf; -} -#endif - - -#ifdef BAN_TEST -unsigned long banAddr = 0x00000000; -unsigned long banMask = 0xffffffff; - -void NET_Ban_f (void) -{ - char addrStr [32]; - char maskStr [32]; - void (*print) (char *fmt, ...); - - if (cmd_source == src_command) - { - if (!sv.active) - { - Cmd_ForwardToServer (); - return; - } - print = Con_Printf; - } - else - { - if (pr_global_struct->deathmatch && !host_client->privileged) - return; - print = SV_ClientPrintf; - } - - switch (Cmd_Argc ()) - { - case 1: - if (((struct in_addr *)&banAddr)->s_addr) - { - Q_strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr)); - Q_strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask)); - print("Banning %s [%s]\n", addrStr, maskStr); - } - else - print("Banning not active\n"); - break; - - case 2: - if (Q_strcasecmp(Cmd_Argv(1), "off") == 0) - banAddr = 0x00000000; - else - banAddr = inet_addr(Cmd_Argv(1)); - banMask = 0xffffffff; - break; - - case 3: - banAddr = inet_addr(Cmd_Argv(1)); - banMask = inet_addr(Cmd_Argv(2)); - break; - - default: - print("BAN ip_address [mask]\n"); - break; - } -} -#endif - - -int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - -#ifdef DEBUG - if (data->cursize == 0) - Sys_Error("Datagram_SendMessage: zero length message\n"); - - if (data->cursize > NET_MAXMESSAGE) - Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize); - - if (sock->canSend == false) - Sys_Error("SendMessage: called with canSend == false\n"); -#endif - - Q_memcpy(sock->sendMessage, data->data, data->cursize); - sock->sendMessageLength = data->cursize; - - if (data->cursize <= MAX_DATAGRAM) - { - dataLen = data->cursize; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence++); - Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->canSend = false; - - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsSent++; - return 1; -} - - -int SendMessageNext (qsocket_t *sock) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - - if (sock->sendMessageLength <= MAX_DATAGRAM) - { - dataLen = sock->sendMessageLength; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence++); - Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->sendNext = false; - - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsSent++; - return 1; -} - - -int ReSendMessage (qsocket_t *sock) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - - if (sock->sendMessageLength <= MAX_DATAGRAM) - { - dataLen = sock->sendMessageLength; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence - 1); - Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->sendNext = false; - - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsReSent++; - return 1; -} - - -qboolean Datagram_CanSendMessage (qsocket_t *sock) -{ - if (sock->sendNext) - SendMessageNext (sock); - - return sock->canSend; -} - - -qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock) -{ - return true; -} - - -int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - int packetLen; - -#ifdef DEBUG - if (data->cursize == 0) - Sys_Error("Datagram_SendUnreliableMessage: zero length message\n"); - - if (data->cursize > MAX_DATAGRAM) - Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize); -#endif - - packetLen = NET_HEADERSIZE + data->cursize; - - packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE); - packetBuffer.sequence = BigLong(sock->unreliableSendSequence++); - Q_memcpy (packetBuffer.data, data->data, data->cursize); - - if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - packetsSent++; - return 1; -} - - -int Datagram_GetMessage (qsocket_t *sock) -{ - unsigned int length; - unsigned int flags; - int ret = 0; - struct qsockaddr readaddr; - unsigned int sequence; - unsigned int count; - - if (!sock->canSend) - if ((net_time - sock->lastSendTime) > 1.0) - ReSendMessage (sock); - - while(1) - { - length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); - -// if ((rand() & 255) > 220) -// continue; - - if (length == 0) - break; - - if (length == -1) - { - Con_Printf("Read error\n"); - return -1; - } - - if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0) - { -#ifdef DEBUG - Con_DPrintf("Forged packet received\n"); - Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr)); - Con_DPrintf("Received: %s\n", StrAddr (&readaddr)); -#endif - continue; - } - - if (length < NET_HEADERSIZE) - { - shortPacketCount++; - continue; - } - - length = BigLong(packetBuffer.length); - flags = length & (~NETFLAG_LENGTH_MASK); - length &= NETFLAG_LENGTH_MASK; - - if (flags & NETFLAG_CTL) - continue; - - sequence = BigLong(packetBuffer.sequence); - packetsReceived++; - - if (flags & NETFLAG_UNRELIABLE) - { - if (sequence < sock->unreliableReceiveSequence) - { - Con_DPrintf("Got a stale datagram\n"); - ret = 0; - break; - } - if (sequence != sock->unreliableReceiveSequence) - { - count = sequence - sock->unreliableReceiveSequence; - droppedDatagrams += count; - Con_DPrintf("Dropped %u datagram(s)\n", count); - } - sock->unreliableReceiveSequence = sequence + 1; - - length -= NET_HEADERSIZE; - - SZ_Clear (&net_message); - SZ_Write (&net_message, packetBuffer.data, length); - - ret = 2; - break; - } - - if (flags & NETFLAG_ACK) - { - if (sequence != (sock->sendSequence - 1)) - { - Con_DPrintf("Stale ACK received\n"); - continue; - } - if (sequence == sock->ackSequence) - { - sock->ackSequence++; - if (sock->ackSequence != sock->sendSequence) - Con_DPrintf("ack sequencing error\n"); - } - else - { - Con_DPrintf("Duplicate ACK received\n"); - continue; - } - sock->sendMessageLength -= MAX_DATAGRAM; - if (sock->sendMessageLength > 0) - { - Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength); - sock->sendNext = true; - } - else - { - sock->sendMessageLength = 0; - sock->canSend = true; - } - continue; - } - - if (flags & NETFLAG_DATA) - { - packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK); - packetBuffer.sequence = BigLong(sequence); - sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr); - - if (sequence != sock->receiveSequence) - { - receivedDuplicateCount++; - continue; - } - sock->receiveSequence++; - - length -= NET_HEADERSIZE; - - if (flags & NETFLAG_EOM) - { - SZ_Clear(&net_message); - SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength); - SZ_Write(&net_message, packetBuffer.data, length); - sock->receiveMessageLength = 0; - - ret = 1; - break; - } - - Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length); - sock->receiveMessageLength += length; - continue; - } - } - - if (sock->sendNext) - SendMessageNext (sock); - - return ret; -} - - -void PrintStats(qsocket_t *s) -{ - Con_Printf("canSend = %4u \n", s->canSend); - Con_Printf("sendSeq = %4u ", s->sendSequence); - Con_Printf("recvSeq = %4u \n", s->receiveSequence); - Con_Printf("\n"); -} - -void NET_Stats_f (void) -{ - qsocket_t *s; - - if (Cmd_Argc () == 1) - { - Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent); - Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived); - Con_Printf("reliable messages sent = %i\n", messagesSent); - Con_Printf("reliable messages received = %i\n", messagesReceived); - Con_Printf("packetsSent = %i\n", packetsSent); - Con_Printf("packetsReSent = %i\n", packetsReSent); - Con_Printf("packetsReceived = %i\n", packetsReceived); - Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount); - Con_Printf("shortPacketCount = %i\n", shortPacketCount); - Con_Printf("droppedDatagrams = %i\n", droppedDatagrams); - } - else if (Q_strcmp(Cmd_Argv(1), "*") == 0) - { - for (s = net_activeSockets; s; s = s->next) - PrintStats(s); - for (s = net_freeSockets; s; s = s->next) - PrintStats(s); - } - else - { - for (s = net_activeSockets; s; s = s->next) - if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0) - break; - if (s == NULL) - for (s = net_freeSockets; s; s = s->next) - if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0) - break; - if (s == NULL) - return; - PrintStats(s); - } -} - - -static qboolean testInProgress = false; -static int testPollCount; -static int testDriver; -static int testSocket; - -static void Test_Poll(void); -PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll}; - -static void Test_Poll(void) -{ - struct qsockaddr clientaddr; - int control; - int len; - char name[32]; - char address[64]; - int colors; - int frags; - int connectTime; - byte playerNumber; - - net_landriverlevel = testDriver; - - while (1) - { - len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr); - if (len < sizeof(int)) - break; - - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - break; - if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) - break; - if ((control & NETFLAG_LENGTH_MASK) != len) - break; - - if (MSG_ReadByte() != CCREP_PLAYER_INFO) - Sys_Error("Unexpected repsonse to Player Info request\n"); - - playerNumber = MSG_ReadByte(); - Q_strcpy(name, MSG_ReadString()); - colors = MSG_ReadLong(); - frags = MSG_ReadLong(); - connectTime = MSG_ReadLong(); - Q_strcpy(address, MSG_ReadString()); - - Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address); - } - - testPollCount--; - if (testPollCount) - { - SchedulePollProcedure(&testPollProcedure, 0.1); - } - else - { - dfunc.CloseSocket(testSocket); - testInProgress = false; - } -} - -static void Test_f (void) -{ - char *host; - int n; - int max = MAX_SCOREBOARD; - struct qsockaddr sendaddr; - - if (testInProgress) - return; - - host = Cmd_Argv (1); - - if (host && hostCacheCount) - { - for (n = 0; n < hostCacheCount; n++) - if (Q_strcasecmp (host, hostcache[n].name) == 0) - { - if (hostcache[n].driver != myDriverLevel) - continue; - net_landriverlevel = hostcache[n].ldriver; - max = hostcache[n].maxusers; - Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); - break; - } - if (n < hostCacheCount) - goto JustDoIt; - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (!net_landrivers[net_landriverlevel].initialized) - continue; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) != -1) - break; - } - if (net_landriverlevel == net_numlandrivers) - return; - -JustDoIt: - testSocket = dfunc.OpenSocket(0); - if (testSocket == -1) - return; - - testInProgress = true; - testPollCount = 20; - testDriver = net_landriverlevel; - - for (n = 0; n < max; n++) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO); - MSG_WriteByte(&net_message, n); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr); - } - SZ_Clear(&net_message); - SchedulePollProcedure(&testPollProcedure, 0.1); -} - - -static qboolean test2InProgress = false; -static int test2Driver; -static int test2Socket; - -static void Test2_Poll(void); -PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll}; - -static void Test2_Poll(void) -{ - struct qsockaddr clientaddr; - int control; - int len; - char name[256]; - char value[256]; - - net_landriverlevel = test2Driver; - name[0] = 0; - - len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr); - if (len < sizeof(int)) - goto Reschedule; - - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - goto Error; - if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) - goto Error; - if ((control & NETFLAG_LENGTH_MASK) != len) - goto Error; - - if (MSG_ReadByte() != CCREP_RULE_INFO) - goto Error; - - Q_strcpy(name, MSG_ReadString()); - if (name[0] == 0) - goto Done; - Q_strcpy(value, MSG_ReadString()); - - Con_Printf("%-16.16s %-16.16s\n", name, value); - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_RULE_INFO); - MSG_WriteString(&net_message, name); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - -Reschedule: - SchedulePollProcedure(&test2PollProcedure, 0.05); - return; - -Error: - Con_Printf("Unexpected repsonse to Rule Info request\n"); -Done: - dfunc.CloseSocket(test2Socket); - test2InProgress = false; - return; -} - -static void Test2_f (void) -{ - char *host; - int n; - struct qsockaddr sendaddr; - - if (test2InProgress) - return; - - host = Cmd_Argv (1); - - if (host && hostCacheCount) - { - for (n = 0; n < hostCacheCount; n++) - if (Q_strcasecmp (host, hostcache[n].name) == 0) - { - if (hostcache[n].driver != myDriverLevel) - continue; - net_landriverlevel = hostcache[n].ldriver; - Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); - break; - } - if (n < hostCacheCount) - goto JustDoIt; - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (!net_landrivers[net_landriverlevel].initialized) - continue; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) != -1) - break; - } - if (net_landriverlevel == net_numlandrivers) - return; - -JustDoIt: - test2Socket = dfunc.OpenSocket(0); - if (test2Socket == -1) - return; - - test2InProgress = true; - test2Driver = net_landriverlevel; - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_RULE_INFO); - MSG_WriteString(&net_message, ""); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr); - SZ_Clear(&net_message); - SchedulePollProcedure(&test2PollProcedure, 0.05); -} - - -int Datagram_Init (void) -{ - int i; - int csock; - - myDriverLevel = net_driverlevel; - Cmd_AddCommand ("net_stats", NET_Stats_f); - - if (COM_CheckParm("-nolan")) - return -1; - - for (i = 0; i < net_numlandrivers; i++) - { - csock = net_landrivers[i].Init (); - if (csock == -1) - continue; - net_landrivers[i].initialized = true; - net_landrivers[i].controlSock = csock; - } - -#ifdef BAN_TEST - Cmd_AddCommand ("ban", NET_Ban_f); -#endif - Cmd_AddCommand ("test", Test_f); - Cmd_AddCommand ("test2", Test2_f); - - return 0; -} - - -void Datagram_Shutdown (void) -{ - int i; - -// -// shutdown the lan drivers -// - for (i = 0; i < net_numlandrivers; i++) - { - if (net_landrivers[i].initialized) - { - net_landrivers[i].Shutdown (); - net_landrivers[i].initialized = false; - } - } -} - - -void Datagram_Close (qsocket_t *sock) -{ - sfunc.CloseSocket(sock->socket); -} - - -void Datagram_Listen (qboolean state) -{ - int i; - - for (i = 0; i < net_numlandrivers; i++) - if (net_landrivers[i].initialized) - net_landrivers[i].Listen (state); -} - - -static qsocket_t *_Datagram_CheckNewConnections (void) -{ - struct qsockaddr clientaddr; - struct qsockaddr newaddr; - int newsock; - int acceptsock; - qsocket_t *sock; - qsocket_t *s; - int len; - int command; - int control; - int ret; - - acceptsock = dfunc.CheckNewConnections(); - if (acceptsock == -1) - return NULL; - - SZ_Clear(&net_message); - - len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); - if (len < sizeof(int)) - return NULL; - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - return NULL; - if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) - return NULL; - if ((control & NETFLAG_LENGTH_MASK) != len) - return NULL; - - command = MSG_ReadByte(); - if (command == CCREQ_SERVER_INFO) - { - if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_SERVER_INFO); - dfunc.GetSocketAddr(acceptsock, &newaddr); - MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); - MSG_WriteString(&net_message, hostname.string); - MSG_WriteString(&net_message, sv.name); - MSG_WriteByte(&net_message, net_activeconnections); - MSG_WriteByte(&net_message, svs.maxclients); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - - if (command == CCREQ_PLAYER_INFO) - { - int playerNumber; - int activeNumber; - int clientNumber; - client_t *client; - - playerNumber = MSG_ReadByte(); - activeNumber = -1; - for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) - { - if (client->active) - { - activeNumber++; - if (activeNumber == playerNumber) - break; - } - } - if (clientNumber == svs.maxclients) - return NULL; - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_PLAYER_INFO); - MSG_WriteByte(&net_message, playerNumber); - MSG_WriteString(&net_message, client->name); - MSG_WriteLong(&net_message, client->colors); - MSG_WriteLong(&net_message, (int)client->edict->v.frags); - MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); - MSG_WriteString(&net_message, client->netconnection->address); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return NULL; - } - - if (command == CCREQ_RULE_INFO) - { - char *prevCvarName; - cvar_t *var; - - // find the search start location - prevCvarName = MSG_ReadString(); - if (*prevCvarName) - { - var = Cvar_FindVar (prevCvarName); - if (!var) - return NULL; - var = var->next; - } - else - var = cvar_vars; - - // search for the next server cvar - while (var) - { - if (var->server) - break; - var = var->next; - } - - // send the response - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_RULE_INFO); - if (var) - { - MSG_WriteString(&net_message, var->name); - MSG_WriteString(&net_message, var->string); - } - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return NULL; - } - - if (command != CCREQ_CONNECT) - return NULL; - - if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - if (MSG_ReadByte() != NET_PROTOCOL_VERSION) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "Incompatible version.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - -#ifdef BAN_TEST - // check for a ban - if (clientaddr.sa_family == AF_INET) - { - unsigned long testAddr; - testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; - if ((testAddr & banMask) == banAddr) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "You have been banned.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - } -#endif - - // see if this guy is already connected - for (s = net_activeSockets; s; s = s->next) - { - if (s->driver != net_driverlevel) - continue; - ret = dfunc.AddrCompare(&clientaddr, &s->addr); - if (ret >= 0) - { - // is this a duplicate connection reqeust? - if (ret == 0 && net_time - s->connecttime < 2.0) - { - // yes, so send a duplicate reply - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_ACCEPT); - dfunc.GetSocketAddr(s->socket, &newaddr); - MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - // it's somebody coming back in from a crash/disconnect - // so close the old qsocket and let their retry get them back in - NET_Close(s); - return NULL; - } - } - - // allocate a QSocket - sock = NET_NewQSocket (); - if (sock == NULL) - { - // no room; try to let him know - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "Server is full.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - - // allocate a network socket - newsock = dfunc.OpenSocket(0); - if (newsock == -1) - { - NET_FreeQSocket(sock); - return NULL; - } - - // connect to the client - if (dfunc.Connect (newsock, &clientaddr) == -1) - { - dfunc.CloseSocket(newsock); - NET_FreeQSocket(sock); - return NULL; - } - - // everything is allocated, just fill in the details - sock->socket = newsock; - sock->landriver = net_landriverlevel; - sock->addr = clientaddr; - Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr)); - - // send him back the info about the server connection he has been allocated - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_ACCEPT); - dfunc.GetSocketAddr(newsock, &newaddr); - MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); -// MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return sock; -} - -qsocket_t *Datagram_CheckNewConnections (void) -{ - qsocket_t *ret = NULL; - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - if ((ret = _Datagram_CheckNewConnections ()) != NULL) - break; - return ret; -} - - -static void _Datagram_SearchForHosts (qboolean xmit) -{ - int ret; - int n; - int i; - struct qsockaddr readaddr; - struct qsockaddr myaddr; - int control; - - dfunc.GetSocketAddr (dfunc.controlSock, &myaddr); - if (xmit) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); - MSG_WriteString(&net_message, "QUAKE"); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize); - SZ_Clear(&net_message); - } - - while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) - { - if (ret < sizeof(int)) - continue; - net_message.cursize = ret; - - // don't answer our own query - if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0) - continue; - - // is the cache full? - if (hostCacheCount == HOSTCACHESIZE) - continue; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - continue; - if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) - continue; - if ((control & NETFLAG_LENGTH_MASK) != ret) - continue; - - if (MSG_ReadByte() != CCREP_SERVER_INFO) - continue; - - dfunc.GetAddrFromName(MSG_ReadString(), &readaddr); - // search the cache for this server - for (n = 0; n < hostCacheCount; n++) - if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0) - break; - - // is it already there? - if (n < hostCacheCount) - continue; - - // add it - hostCacheCount++; - Q_strcpy(hostcache[n].name, MSG_ReadString()); - Q_strcpy(hostcache[n].map, MSG_ReadString()); - hostcache[n].users = MSG_ReadByte(); - hostcache[n].maxusers = MSG_ReadByte(); - if (MSG_ReadByte() != NET_PROTOCOL_VERSION) - { - Q_strcpy(hostcache[n].cname, hostcache[n].name); - hostcache[n].cname[14] = 0; - Q_strcpy(hostcache[n].name, "*"); - Q_strcat(hostcache[n].name, hostcache[n].cname); - } - Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr)); - hostcache[n].driver = net_driverlevel; - hostcache[n].ldriver = net_landriverlevel; - Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr)); - - // check for a name conflict - for (i = 0; i < hostCacheCount; i++) - { - if (i == n) - continue; - if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0) - { - i = Q_strlen(hostcache[n].name); - if (i < 15 && hostcache[n].name[i-1] > '8') - { - hostcache[n].name[i] = '0'; - hostcache[n].name[i+1] = 0; - } - else - hostcache[n].name[i-1]++; - i = -1; - } - } - } -} - -void Datagram_SearchForHosts (qboolean xmit) -{ - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (hostCacheCount == HOSTCACHESIZE) - break; - if (net_landrivers[net_landriverlevel].initialized) - _Datagram_SearchForHosts (xmit); - } -} - - -static qsocket_t *_Datagram_Connect (char *host) -{ - struct qsockaddr sendaddr; - struct qsockaddr readaddr; - qsocket_t *sock; - int newsock; - int ret; - int reps; - double start_time; - int control; - char *reason; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) == -1) - return NULL; - - newsock = dfunc.OpenSocket (0); - if (newsock == -1) - return NULL; - - sock = NET_NewQSocket (); - if (sock == NULL) - goto ErrorReturn2; - sock->socket = newsock; - sock->landriver = net_landriverlevel; - - // connect to the host - if (dfunc.Connect (newsock, &sendaddr) == -1) - goto ErrorReturn; - - // send the connection request - Con_Printf("trying...\n"); SCR_UpdateScreen (); - start_time = net_time; - - for (reps = 0; reps < 3; reps++) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_CONNECT); - MSG_WriteString(&net_message, "QUAKE"); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr); - SZ_Clear(&net_message); - do - { - ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr); - // if we got something, validate it - if (ret > 0) - { - // is it from the right place? - if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0) - { -#ifdef DEBUG - Con_Printf("wrong reply address\n"); - Con_Printf("Expected: %s\n", StrAddr (&sendaddr)); - Con_Printf("Received: %s\n", StrAddr (&readaddr)); - SCR_UpdateScreen (); -#endif - ret = 0; - continue; - } - - if (ret < sizeof(int)) - { - ret = 0; - continue; - } - - net_message.cursize = ret; - MSG_BeginReading (); - - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - { - ret = 0; - continue; - } - if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) - { - ret = 0; - continue; - } - if ((control & NETFLAG_LENGTH_MASK) != ret) - { - ret = 0; - continue; - } - } - } - while (ret == 0 && (SetNetTime() - start_time) < 2.5); - if (ret) - break; - Con_Printf("still trying...\n"); SCR_UpdateScreen (); - start_time = SetNetTime(); - } - - if (ret == 0) - { - reason = "No Response"; - Con_Printf("%s\n", reason); - Q_strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - if (ret == -1) - { - reason = "Network Error"; - Con_Printf("%s\n", reason); - Q_strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - ret = MSG_ReadByte(); - if (ret == CCREP_REJECT) - { - reason = MSG_ReadString(); - Con_Printf(reason); - Q_strncpy(m_return_reason, reason, 31); - goto ErrorReturn; - } - - if (ret == CCREP_ACCEPT) - { - Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr)); - dfunc.SetSocketPort (&sock->addr, MSG_ReadLong()); - } - else - { - reason = "Bad Response"; - Con_Printf("%s\n", reason); - Q_strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - dfunc.GetNameFromAddr (&sendaddr, sock->address); - - Con_Printf ("Connection accepted\n"); - sock->lastMessageTime = SetNetTime(); - - // switch the connection to the specified address - if (dfunc.Connect (newsock, &sock->addr) == -1) - { - reason = "Connect to Game failed"; - Con_Printf("%s\n", reason); - Q_strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - m_return_onerror = false; - return sock; - -ErrorReturn: - NET_FreeQSocket(sock); -ErrorReturn2: - dfunc.CloseSocket(newsock); - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - } - return NULL; -} - -qsocket_t *Datagram_Connect (char *host) -{ - qsocket_t *ret = NULL; - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - if ((ret = _Datagram_Connect (host)) != NULL) - break; - return ret; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_dgrm.c + +// This is enables a simple IP banning mechanism +#define BAN_TEST + +#ifdef BAN_TEST +#if defined(_WIN32) +#include +#elif defined (NeXT) +#include +#include +#else +#define AF_INET 2 /* internet */ +struct in_addr +{ + union + { + struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { unsigned short s_w1,s_w2; } S_un_w; + unsigned long S_addr; + } S_un; +}; +#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ +struct sockaddr_in +{ + short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; +char *inet_ntoa(struct in_addr in); +unsigned long inet_addr(const char *cp); +#endif +#endif // BAN_TEST + +#include "quakedef.h" +#include "net_dgrm.h" + +// these two macros are to make the code more readable +#define sfunc net_landrivers[sock->landriver] +#define dfunc net_landrivers[net_landriverlevel] + +static int net_landriverlevel; + +/* statistic counters */ +int packetsSent = 0; +int packetsReSent = 0; +int packetsReceived = 0; +int receivedDuplicateCount = 0; +int shortPacketCount = 0; +int droppedDatagrams; + +static int myDriverLevel; + +struct +{ + unsigned int length; + unsigned int sequence; + byte data[MAX_DATAGRAM]; +} packetBuffer; + +extern int m_return_state; +extern int m_state; +extern qboolean m_return_onerror; +extern char m_return_reason[32]; + + +#ifdef DEBUG +char *StrAddr (struct qsockaddr *addr) +{ + static char buf[34]; + byte *p = (byte *)addr; + int n; + + for (n = 0; n < 16; n++) + sprintf (buf + n * 2, "%02x", *p++); + return buf; +} +#endif + + +#ifdef BAN_TEST +unsigned long banAddr = 0x00000000; +unsigned long banMask = 0xffffffff; + +void NET_Ban_f (void) +{ + char addrStr [32]; + char maskStr [32]; + void (*print) (char *fmt, ...); + + if (cmd_source == src_command) + { + if (!sv.active) + { + Cmd_ForwardToServer (); + return; + } + print = Con_Printf; + } + else + { + if (pr_global_struct->deathmatch && !host_client->privileged) + return; + print = SV_ClientPrintf; + } + + switch (Cmd_Argc ()) + { + case 1: + if (((struct in_addr *)&banAddr)->s_addr) + { + Q_strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr)); + Q_strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask)); + print("Banning %s [%s]\n", addrStr, maskStr); + } + else + print("Banning not active\n"); + break; + + case 2: + if (Q_strcasecmp(Cmd_Argv(1), "off") == 0) + banAddr = 0x00000000; + else + banAddr = inet_addr(Cmd_Argv(1)); + banMask = 0xffffffff; + break; + + case 3: + banAddr = inet_addr(Cmd_Argv(1)); + banMask = inet_addr(Cmd_Argv(2)); + break; + + default: + print("BAN ip_address [mask]\n"); + break; + } +} +#endif + + +int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + +#ifdef DEBUG + if (data->cursize == 0) + Sys_Error("Datagram_SendMessage: zero length message\n"); + + if (data->cursize > NET_MAXMESSAGE) + Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize); + + if (sock->canSend == false) + Sys_Error("SendMessage: called with canSend == false\n"); +#endif + + Q_memcpy(sock->sendMessage, data->data, data->cursize); + sock->sendMessageLength = data->cursize; + + if (data->cursize <= MAX_DATAGRAM) + { + dataLen = data->cursize; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence++); + Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->canSend = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsSent++; + return 1; +} + + +int SendMessageNext (qsocket_t *sock) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + + if (sock->sendMessageLength <= MAX_DATAGRAM) + { + dataLen = sock->sendMessageLength; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence++); + Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->sendNext = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsSent++; + return 1; +} + + +int ReSendMessage (qsocket_t *sock) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + + if (sock->sendMessageLength <= MAX_DATAGRAM) + { + dataLen = sock->sendMessageLength; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence - 1); + Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->sendNext = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsReSent++; + return 1; +} + + +qboolean Datagram_CanSendMessage (qsocket_t *sock) +{ + if (sock->sendNext) + SendMessageNext (sock); + + return sock->canSend; +} + + +qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock) +{ + return true; +} + + +int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) +{ + int packetLen; + +#ifdef DEBUG + if (data->cursize == 0) + Sys_Error("Datagram_SendUnreliableMessage: zero length message\n"); + + if (data->cursize > MAX_DATAGRAM) + Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize); +#endif + + packetLen = NET_HEADERSIZE + data->cursize; + + packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE); + packetBuffer.sequence = BigLong(sock->unreliableSendSequence++); + Q_memcpy (packetBuffer.data, data->data, data->cursize); + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + packetsSent++; + return 1; +} + + +int Datagram_GetMessage (qsocket_t *sock) +{ + unsigned int length; + unsigned int flags; + int ret = 0; + struct qsockaddr readaddr; + unsigned int sequence; + unsigned int count; + + if (!sock->canSend) + if ((net_time - sock->lastSendTime) > 1.0) + ReSendMessage (sock); + + while(1) + { + length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); + +// if ((rand() & 255) > 220) +// continue; + + if (length == 0) + break; + + if (length == -1) + { + Con_Printf("Read error\n"); + return -1; + } + + if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0) + { +#ifdef DEBUG + Con_DPrintf("Forged packet received\n"); + Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr)); + Con_DPrintf("Received: %s\n", StrAddr (&readaddr)); +#endif + continue; + } + + if (length < NET_HEADERSIZE) + { + shortPacketCount++; + continue; + } + + length = BigLong(packetBuffer.length); + flags = length & (~NETFLAG_LENGTH_MASK); + length &= NETFLAG_LENGTH_MASK; + + if (flags & NETFLAG_CTL) + continue; + + sequence = BigLong(packetBuffer.sequence); + packetsReceived++; + + if (flags & NETFLAG_UNRELIABLE) + { + if (sequence < sock->unreliableReceiveSequence) + { + Con_DPrintf("Got a stale datagram\n"); + ret = 0; + break; + } + if (sequence != sock->unreliableReceiveSequence) + { + count = sequence - sock->unreliableReceiveSequence; + droppedDatagrams += count; + Con_DPrintf("Dropped %u datagram(s)\n", count); + } + sock->unreliableReceiveSequence = sequence + 1; + + length -= NET_HEADERSIZE; + + SZ_Clear (&net_message); + SZ_Write (&net_message, packetBuffer.data, length); + + ret = 2; + break; + } + + if (flags & NETFLAG_ACK) + { + if (sequence != (sock->sendSequence - 1)) + { + Con_DPrintf("Stale ACK received\n"); + continue; + } + if (sequence == sock->ackSequence) + { + sock->ackSequence++; + if (sock->ackSequence != sock->sendSequence) + Con_DPrintf("ack sequencing error\n"); + } + else + { + Con_DPrintf("Duplicate ACK received\n"); + continue; + } + sock->sendMessageLength -= MAX_DATAGRAM; + if (sock->sendMessageLength > 0) + { + Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength); + sock->sendNext = true; + } + else + { + sock->sendMessageLength = 0; + sock->canSend = true; + } + continue; + } + + if (flags & NETFLAG_DATA) + { + packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK); + packetBuffer.sequence = BigLong(sequence); + sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr); + + if (sequence != sock->receiveSequence) + { + receivedDuplicateCount++; + continue; + } + sock->receiveSequence++; + + length -= NET_HEADERSIZE; + + if (flags & NETFLAG_EOM) + { + SZ_Clear(&net_message); + SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength); + SZ_Write(&net_message, packetBuffer.data, length); + sock->receiveMessageLength = 0; + + ret = 1; + break; + } + + Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length); + sock->receiveMessageLength += length; + continue; + } + } + + if (sock->sendNext) + SendMessageNext (sock); + + return ret; +} + + +void PrintStats(qsocket_t *s) +{ + Con_Printf("canSend = %4u \n", s->canSend); + Con_Printf("sendSeq = %4u ", s->sendSequence); + Con_Printf("recvSeq = %4u \n", s->receiveSequence); + Con_Printf("\n"); +} + +void NET_Stats_f (void) +{ + qsocket_t *s; + + if (Cmd_Argc () == 1) + { + Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent); + Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived); + Con_Printf("reliable messages sent = %i\n", messagesSent); + Con_Printf("reliable messages received = %i\n", messagesReceived); + Con_Printf("packetsSent = %i\n", packetsSent); + Con_Printf("packetsReSent = %i\n", packetsReSent); + Con_Printf("packetsReceived = %i\n", packetsReceived); + Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount); + Con_Printf("shortPacketCount = %i\n", shortPacketCount); + Con_Printf("droppedDatagrams = %i\n", droppedDatagrams); + } + else if (Q_strcmp(Cmd_Argv(1), "*") == 0) + { + for (s = net_activeSockets; s; s = s->next) + PrintStats(s); + for (s = net_freeSockets; s; s = s->next) + PrintStats(s); + } + else + { + for (s = net_activeSockets; s; s = s->next) + if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0) + break; + if (s == NULL) + for (s = net_freeSockets; s; s = s->next) + if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0) + break; + if (s == NULL) + return; + PrintStats(s); + } +} + + +static qboolean testInProgress = false; +static int testPollCount; +static int testDriver; +static int testSocket; + +static void Test_Poll(void); +PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll}; + +static void Test_Poll(void) +{ + struct qsockaddr clientaddr; + int control; + int len; + char name[32]; + char address[64]; + int colors; + int frags; + int connectTime; + byte playerNumber; + + net_landriverlevel = testDriver; + + while (1) + { + len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + break; + + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + break; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + break; + if ((control & NETFLAG_LENGTH_MASK) != len) + break; + + if (MSG_ReadByte() != CCREP_PLAYER_INFO) + Sys_Error("Unexpected repsonse to Player Info request\n"); + + playerNumber = MSG_ReadByte(); + Q_strcpy(name, MSG_ReadString()); + colors = MSG_ReadLong(); + frags = MSG_ReadLong(); + connectTime = MSG_ReadLong(); + Q_strcpy(address, MSG_ReadString()); + + Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address); + } + + testPollCount--; + if (testPollCount) + { + SchedulePollProcedure(&testPollProcedure, 0.1); + } + else + { + dfunc.CloseSocket(testSocket); + testInProgress = false; + } +} + +static void Test_f (void) +{ + char *host; + int n; + int max = MAX_SCOREBOARD; + struct qsockaddr sendaddr; + + if (testInProgress) + return; + + host = Cmd_Argv (1); + + if (host && hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (Q_strcasecmp (host, hostcache[n].name) == 0) + { + if (hostcache[n].driver != myDriverLevel) + continue; + net_landriverlevel = hostcache[n].ldriver; + max = hostcache[n].maxusers; + Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (!net_landrivers[net_landriverlevel].initialized) + continue; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) != -1) + break; + } + if (net_landriverlevel == net_numlandrivers) + return; + +JustDoIt: + testSocket = dfunc.OpenSocket(0); + if (testSocket == -1) + return; + + testInProgress = true; + testPollCount = 20; + testDriver = net_landriverlevel; + + for (n = 0; n < max; n++) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO); + MSG_WriteByte(&net_message, n); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr); + } + SZ_Clear(&net_message); + SchedulePollProcedure(&testPollProcedure, 0.1); +} + + +static qboolean test2InProgress = false; +static int test2Driver; +static int test2Socket; + +static void Test2_Poll(void); +PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll}; + +static void Test2_Poll(void) +{ + struct qsockaddr clientaddr; + int control; + int len; + char name[256]; + char value[256]; + + net_landriverlevel = test2Driver; + name[0] = 0; + + len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + goto Reschedule; + + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + goto Error; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + goto Error; + if ((control & NETFLAG_LENGTH_MASK) != len) + goto Error; + + if (MSG_ReadByte() != CCREP_RULE_INFO) + goto Error; + + Q_strcpy(name, MSG_ReadString()); + if (name[0] == 0) + goto Done; + Q_strcpy(value, MSG_ReadString()); + + Con_Printf("%-16.16s %-16.16s\n", name, value); + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_RULE_INFO); + MSG_WriteString(&net_message, name); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + +Reschedule: + SchedulePollProcedure(&test2PollProcedure, 0.05); + return; + +Error: + Con_Printf("Unexpected repsonse to Rule Info request\n"); +Done: + dfunc.CloseSocket(test2Socket); + test2InProgress = false; + return; +} + +static void Test2_f (void) +{ + char *host; + int n; + struct qsockaddr sendaddr; + + if (test2InProgress) + return; + + host = Cmd_Argv (1); + + if (host && hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (Q_strcasecmp (host, hostcache[n].name) == 0) + { + if (hostcache[n].driver != myDriverLevel) + continue; + net_landriverlevel = hostcache[n].ldriver; + Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (!net_landrivers[net_landriverlevel].initialized) + continue; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) != -1) + break; + } + if (net_landriverlevel == net_numlandrivers) + return; + +JustDoIt: + test2Socket = dfunc.OpenSocket(0); + if (test2Socket == -1) + return; + + test2InProgress = true; + test2Driver = net_landriverlevel; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_RULE_INFO); + MSG_WriteString(&net_message, ""); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr); + SZ_Clear(&net_message); + SchedulePollProcedure(&test2PollProcedure, 0.05); +} + + +int Datagram_Init (void) +{ + int i; + int csock; + + myDriverLevel = net_driverlevel; + Cmd_AddCommand ("net_stats", NET_Stats_f); + + if (COM_CheckParm("-nolan")) + return -1; + + for (i = 0; i < net_numlandrivers; i++) + { + csock = net_landrivers[i].Init (); + if (csock == -1) + continue; + net_landrivers[i].initialized = true; + net_landrivers[i].controlSock = csock; + } + +#ifdef BAN_TEST + Cmd_AddCommand ("ban", NET_Ban_f); +#endif + Cmd_AddCommand ("test", Test_f); + Cmd_AddCommand ("test2", Test2_f); + + return 0; +} + + +void Datagram_Shutdown (void) +{ + int i; + +// +// shutdown the lan drivers +// + for (i = 0; i < net_numlandrivers; i++) + { + if (net_landrivers[i].initialized) + { + net_landrivers[i].Shutdown (); + net_landrivers[i].initialized = false; + } + } +} + + +void Datagram_Close (qsocket_t *sock) +{ + sfunc.CloseSocket(sock->socket); +} + + +void Datagram_Listen (qboolean state) +{ + int i; + + for (i = 0; i < net_numlandrivers; i++) + if (net_landrivers[i].initialized) + net_landrivers[i].Listen (state); +} + + +static qsocket_t *_Datagram_CheckNewConnections (void) +{ + struct qsockaddr clientaddr; + struct qsockaddr newaddr; + int newsock; + int acceptsock; + qsocket_t *sock; + qsocket_t *s; + int len; + int command; + int control; + int ret; + + acceptsock = dfunc.CheckNewConnections(); + if (acceptsock == -1) + return NULL; + + SZ_Clear(&net_message); + + len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + return NULL; + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + return NULL; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + return NULL; + if ((control & NETFLAG_LENGTH_MASK) != len) + return NULL; + + command = MSG_ReadByte(); + if (command == CCREQ_SERVER_INFO) + { + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_SERVER_INFO); + dfunc.GetSocketAddr(acceptsock, &newaddr); + MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); + MSG_WriteString(&net_message, hostname.string); + MSG_WriteString(&net_message, sv.name); + MSG_WriteByte(&net_message, net_activeconnections); + MSG_WriteByte(&net_message, svs.maxclients); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + + if (command == CCREQ_PLAYER_INFO) + { + int playerNumber; + int activeNumber; + int clientNumber; + client_t *client; + + playerNumber = MSG_ReadByte(); + activeNumber = -1; + for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) + { + if (client->active) + { + activeNumber++; + if (activeNumber == playerNumber) + break; + } + } + if (clientNumber == svs.maxclients) + return NULL; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_PLAYER_INFO); + MSG_WriteByte(&net_message, playerNumber); + MSG_WriteString(&net_message, client->name); + MSG_WriteLong(&net_message, client->colors); + MSG_WriteLong(&net_message, (int)client->edict->v.frags); + MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); + MSG_WriteString(&net_message, client->netconnection->address); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return NULL; + } + + if (command == CCREQ_RULE_INFO) + { + char *prevCvarName; + cvar_t *var; + + // find the search start location + prevCvarName = MSG_ReadString(); + if (*prevCvarName) + { + var = Cvar_FindVar (prevCvarName); + if (!var) + return NULL; + var = var->next; + } + else + var = cvar_vars; + + // search for the next server cvar + while (var) + { + if (var->server) + break; + var = var->next; + } + + // send the response + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_RULE_INFO); + if (var) + { + MSG_WriteString(&net_message, var->name); + MSG_WriteString(&net_message, var->string); + } + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return NULL; + } + + if (command != CCREQ_CONNECT) + return NULL; + + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + if (MSG_ReadByte() != NET_PROTOCOL_VERSION) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "Incompatible version.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + +#ifdef BAN_TEST + // check for a ban + if (clientaddr.sa_family == AF_INET) + { + unsigned long testAddr; + testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; + if ((testAddr & banMask) == banAddr) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "You have been banned.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + } +#endif + + // see if this guy is already connected + for (s = net_activeSockets; s; s = s->next) + { + if (s->driver != net_driverlevel) + continue; + ret = dfunc.AddrCompare(&clientaddr, &s->addr); + if (ret >= 0) + { + // is this a duplicate connection reqeust? + if (ret == 0 && net_time - s->connecttime < 2.0) + { + // yes, so send a duplicate reply + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + dfunc.GetSocketAddr(s->socket, &newaddr); + MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + // it's somebody coming back in from a crash/disconnect + // so close the old qsocket and let their retry get them back in + NET_Close(s); + return NULL; + } + } + + // allocate a QSocket + sock = NET_NewQSocket (); + if (sock == NULL) + { + // no room; try to let him know + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "Server is full.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + + // allocate a network socket + newsock = dfunc.OpenSocket(0); + if (newsock == -1) + { + NET_FreeQSocket(sock); + return NULL; + } + + // connect to the client + if (dfunc.Connect (newsock, &clientaddr) == -1) + { + dfunc.CloseSocket(newsock); + NET_FreeQSocket(sock); + return NULL; + } + + // everything is allocated, just fill in the details + sock->socket = newsock; + sock->landriver = net_landriverlevel; + sock->addr = clientaddr; + Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr)); + + // send him back the info about the server connection he has been allocated + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + dfunc.GetSocketAddr(newsock, &newaddr); + MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); +// MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return sock; +} + +qsocket_t *Datagram_CheckNewConnections (void) +{ + qsocket_t *ret = NULL; + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + if (net_landrivers[net_landriverlevel].initialized) + if ((ret = _Datagram_CheckNewConnections ()) != NULL) + break; + return ret; +} + + +static void _Datagram_SearchForHosts (qboolean xmit) +{ + int ret; + int n; + int i; + struct qsockaddr readaddr; + struct qsockaddr myaddr; + int control; + + dfunc.GetSocketAddr (dfunc.controlSock, &myaddr); + if (xmit) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); + MSG_WriteString(&net_message, "QUAKE"); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize); + SZ_Clear(&net_message); + } + + while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) + { + if (ret < sizeof(int)) + continue; + net_message.cursize = ret; + + // don't answer our own query + if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0) + continue; + + // is the cache full? + if (hostCacheCount == HOSTCACHESIZE) + continue; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + continue; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + continue; + if ((control & NETFLAG_LENGTH_MASK) != ret) + continue; + + if (MSG_ReadByte() != CCREP_SERVER_INFO) + continue; + + dfunc.GetAddrFromName(MSG_ReadString(), &readaddr); + // search the cache for this server + for (n = 0; n < hostCacheCount; n++) + if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0) + break; + + // is it already there? + if (n < hostCacheCount) + continue; + + // add it + hostCacheCount++; + Q_strcpy(hostcache[n].name, MSG_ReadString()); + Q_strcpy(hostcache[n].map, MSG_ReadString()); + hostcache[n].users = MSG_ReadByte(); + hostcache[n].maxusers = MSG_ReadByte(); + if (MSG_ReadByte() != NET_PROTOCOL_VERSION) + { + Q_strcpy(hostcache[n].cname, hostcache[n].name); + hostcache[n].cname[14] = 0; + Q_strcpy(hostcache[n].name, "*"); + Q_strcat(hostcache[n].name, hostcache[n].cname); + } + Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr)); + hostcache[n].driver = net_driverlevel; + hostcache[n].ldriver = net_landriverlevel; + Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr)); + + // check for a name conflict + for (i = 0; i < hostCacheCount; i++) + { + if (i == n) + continue; + if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0) + { + i = Q_strlen(hostcache[n].name); + if (i < 15 && hostcache[n].name[i-1] > '8') + { + hostcache[n].name[i] = '0'; + hostcache[n].name[i+1] = 0; + } + else + hostcache[n].name[i-1]++; + i = -1; + } + } + } +} + +void Datagram_SearchForHosts (qboolean xmit) +{ + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (hostCacheCount == HOSTCACHESIZE) + break; + if (net_landrivers[net_landriverlevel].initialized) + _Datagram_SearchForHosts (xmit); + } +} + + +static qsocket_t *_Datagram_Connect (char *host) +{ + struct qsockaddr sendaddr; + struct qsockaddr readaddr; + qsocket_t *sock; + int newsock; + int ret; + int reps; + double start_time; + int control; + char *reason; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) == -1) + return NULL; + + newsock = dfunc.OpenSocket (0); + if (newsock == -1) + return NULL; + + sock = NET_NewQSocket (); + if (sock == NULL) + goto ErrorReturn2; + sock->socket = newsock; + sock->landriver = net_landriverlevel; + + // connect to the host + if (dfunc.Connect (newsock, &sendaddr) == -1) + goto ErrorReturn; + + // send the connection request + Con_Printf("trying...\n"); SCR_UpdateScreen (); + start_time = net_time; + + for (reps = 0; reps < 3; reps++) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_CONNECT); + MSG_WriteString(&net_message, "QUAKE"); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr); + SZ_Clear(&net_message); + do + { + ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr); + // if we got something, validate it + if (ret > 0) + { + // is it from the right place? + if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0) + { +#ifdef DEBUG + Con_Printf("wrong reply address\n"); + Con_Printf("Expected: %s\n", StrAddr (&sendaddr)); + Con_Printf("Received: %s\n", StrAddr (&readaddr)); + SCR_UpdateScreen (); +#endif + ret = 0; + continue; + } + + if (ret < sizeof(int)) + { + ret = 0; + continue; + } + + net_message.cursize = ret; + MSG_BeginReading (); + + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + { + ret = 0; + continue; + } + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + { + ret = 0; + continue; + } + if ((control & NETFLAG_LENGTH_MASK) != ret) + { + ret = 0; + continue; + } + } + } + while (ret == 0 && (SetNetTime() - start_time) < 2.5); + if (ret) + break; + Con_Printf("still trying...\n"); SCR_UpdateScreen (); + start_time = SetNetTime(); + } + + if (ret == 0) + { + reason = "No Response"; + Con_Printf("%s\n", reason); + Q_strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + if (ret == -1) + { + reason = "Network Error"; + Con_Printf("%s\n", reason); + Q_strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + ret = MSG_ReadByte(); + if (ret == CCREP_REJECT) + { + reason = MSG_ReadString(); + Con_Printf(reason); + Q_strncpy(m_return_reason, reason, 31); + goto ErrorReturn; + } + + if (ret == CCREP_ACCEPT) + { + Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr)); + dfunc.SetSocketPort (&sock->addr, MSG_ReadLong()); + } + else + { + reason = "Bad Response"; + Con_Printf("%s\n", reason); + Q_strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + dfunc.GetNameFromAddr (&sendaddr, sock->address); + + Con_Printf ("Connection accepted\n"); + sock->lastMessageTime = SetNetTime(); + + // switch the connection to the specified address + if (dfunc.Connect (newsock, &sock->addr) == -1) + { + reason = "Connect to Game failed"; + Con_Printf("%s\n", reason); + Q_strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + m_return_onerror = false; + return sock; + +ErrorReturn: + NET_FreeQSocket(sock); +ErrorReturn2: + dfunc.CloseSocket(newsock); + if (m_return_onerror) + { + key_dest = key_menu; + m_state = m_return_state; + m_return_onerror = false; + } + return NULL; +} + +qsocket_t *Datagram_Connect (char *host) +{ + qsocket_t *ret = NULL; + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + if (net_landrivers[net_landriverlevel].initialized) + if ((ret = _Datagram_Connect (host)) != NULL) + break; + return ret; +} diff --git a/WinQuake/net_dgrm.h b/WinQuake/net_dgrm.h index da052e7..aa3c715 100644 --- a/WinQuake/net_dgrm.h +++ b/WinQuake/net_dgrm.h @@ -1,34 +1,34 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_dgrm.h - - -int Datagram_Init (void); -void Datagram_Listen (qboolean state); -void Datagram_SearchForHosts (qboolean xmit); -qsocket_t *Datagram_Connect (char *host); -qsocket_t *Datagram_CheckNewConnections (void); -int Datagram_GetMessage (qsocket_t *sock); -int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data); -int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Datagram_CanSendMessage (qsocket_t *sock); -qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); -void Datagram_Close (qsocket_t *sock); -void Datagram_Shutdown (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_dgrm.h + + +int Datagram_Init (void); +void Datagram_Listen (qboolean state); +void Datagram_SearchForHosts (qboolean xmit); +qsocket_t *Datagram_Connect (char *host); +qsocket_t *Datagram_CheckNewConnections (void); +int Datagram_GetMessage (qsocket_t *sock); +int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data); +int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); +qboolean Datagram_CanSendMessage (qsocket_t *sock); +qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); +void Datagram_Close (qsocket_t *sock); +void Datagram_Shutdown (void); diff --git a/WinQuake/net_dos.c b/WinQuake/net_dos.c index 5dbbdce..8313256 100644 --- a/WinQuake/net_dos.c +++ b/WinQuake/net_dos.c @@ -1,162 +1,162 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -#include "net_loop.h" -#include "net_dgrm.h" -#include "net_ser.h" - -net_driver_t net_drivers[MAX_NET_DRIVERS] = -{ - { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown - } - , - { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown - } - , - { - "Serial", - false, - Serial_Init, - Serial_Listen, - Serial_SearchForHosts, - Serial_Connect, - Serial_CheckNewConnections, - Serial_GetMessage, - Serial_SendMessage, - Serial_SendUnreliableMessage, - Serial_CanSendMessage, - Serial_CanSendUnreliableMessage, - Serial_Close, - Serial_Shutdown - } -}; - -int net_numdrivers = 3; - - -#include "net_bw.h" -#include "net_ipx.h" -#include "net_mp.h" - -net_landriver_t net_landrivers[MAX_NET_DRIVERS] = -{ - { - "Beame & Whiteside TCP/IP", - false, - 0, - BW_Init, - BW_Shutdown, - BW_Listen, - BW_OpenSocket, - BW_CloseSocket, - BW_Connect, - BW_CheckNewConnections, - BW_Read, - BW_Write, - BW_Broadcast, - BW_AddrToString, - BW_StringToAddr, - BW_GetSocketAddr, - BW_GetNameFromAddr, - BW_GetAddrFromName, - BW_AddrCompare, - BW_GetSocketPort, - BW_SetSocketPort - } -, - { - "IPX", - false, - 0, - IPX_Init, - IPX_Shutdown, - IPX_Listen, - IPX_OpenSocket, - IPX_CloseSocket, - IPX_Connect, - IPX_CheckNewConnections, - IPX_Read, - IPX_Write, - IPX_Broadcast, - IPX_AddrToString, - IPX_StringToAddr, - IPX_GetSocketAddr, - IPX_GetNameFromAddr, - IPX_GetAddrFromName, - IPX_AddrCompare, - IPX_GetSocketPort, - IPX_SetSocketPort - } -, - { - "Win95 TCP/IP", - false, - 0, - MPATH_Init, - MPATH_Shutdown, - MPATH_Listen, - MPATH_OpenSocket, - MPATH_CloseSocket, - MPATH_Connect, - MPATH_CheckNewConnections, - MPATH_Read, - MPATH_Write, - MPATH_Broadcast, - MPATH_AddrToString, - MPATH_StringToAddr, - MPATH_GetSocketAddr, - MPATH_GetNameFromAddr, - MPATH_GetAddrFromName, - MPATH_AddrCompare, - MPATH_GetSocketPort, - MPATH_SetSocketPort - } -}; - -int net_numlandrivers = 3; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +#include "net_loop.h" +#include "net_dgrm.h" +#include "net_ser.h" + +net_driver_t net_drivers[MAX_NET_DRIVERS] = +{ + { + "Loopback", + false, + Loop_Init, + Loop_Listen, + Loop_SearchForHosts, + Loop_Connect, + Loop_CheckNewConnections, + Loop_GetMessage, + Loop_SendMessage, + Loop_SendUnreliableMessage, + Loop_CanSendMessage, + Loop_CanSendUnreliableMessage, + Loop_Close, + Loop_Shutdown + } + , + { + "Datagram", + false, + Datagram_Init, + Datagram_Listen, + Datagram_SearchForHosts, + Datagram_Connect, + Datagram_CheckNewConnections, + Datagram_GetMessage, + Datagram_SendMessage, + Datagram_SendUnreliableMessage, + Datagram_CanSendMessage, + Datagram_CanSendUnreliableMessage, + Datagram_Close, + Datagram_Shutdown + } + , + { + "Serial", + false, + Serial_Init, + Serial_Listen, + Serial_SearchForHosts, + Serial_Connect, + Serial_CheckNewConnections, + Serial_GetMessage, + Serial_SendMessage, + Serial_SendUnreliableMessage, + Serial_CanSendMessage, + Serial_CanSendUnreliableMessage, + Serial_Close, + Serial_Shutdown + } +}; + +int net_numdrivers = 3; + + +#include "net_bw.h" +#include "net_ipx.h" +#include "net_mp.h" + +net_landriver_t net_landrivers[MAX_NET_DRIVERS] = +{ + { + "Beame & Whiteside TCP/IP", + false, + 0, + BW_Init, + BW_Shutdown, + BW_Listen, + BW_OpenSocket, + BW_CloseSocket, + BW_Connect, + BW_CheckNewConnections, + BW_Read, + BW_Write, + BW_Broadcast, + BW_AddrToString, + BW_StringToAddr, + BW_GetSocketAddr, + BW_GetNameFromAddr, + BW_GetAddrFromName, + BW_AddrCompare, + BW_GetSocketPort, + BW_SetSocketPort + } +, + { + "IPX", + false, + 0, + IPX_Init, + IPX_Shutdown, + IPX_Listen, + IPX_OpenSocket, + IPX_CloseSocket, + IPX_Connect, + IPX_CheckNewConnections, + IPX_Read, + IPX_Write, + IPX_Broadcast, + IPX_AddrToString, + IPX_StringToAddr, + IPX_GetSocketAddr, + IPX_GetNameFromAddr, + IPX_GetAddrFromName, + IPX_AddrCompare, + IPX_GetSocketPort, + IPX_SetSocketPort + } +, + { + "Win95 TCP/IP", + false, + 0, + MPATH_Init, + MPATH_Shutdown, + MPATH_Listen, + MPATH_OpenSocket, + MPATH_CloseSocket, + MPATH_Connect, + MPATH_CheckNewConnections, + MPATH_Read, + MPATH_Write, + MPATH_Broadcast, + MPATH_AddrToString, + MPATH_StringToAddr, + MPATH_GetSocketAddr, + MPATH_GetNameFromAddr, + MPATH_GetAddrFromName, + MPATH_AddrCompare, + MPATH_GetSocketPort, + MPATH_SetSocketPort + } +}; + +int net_numlandrivers = 3; diff --git a/WinQuake/net_ipx.c b/WinQuake/net_ipx.c index f0ab72e..75ae6fd 100644 --- a/WinQuake/net_ipx.c +++ b/WinQuake/net_ipx.c @@ -1,706 +1,706 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_ipx.c - -#include -#include -#include - -#include "quakedef.h" -#include "dosisms.h" -#include "net_ipx.h" - -#define EIO 5 /* I/O error */ - -#define AF_NETWARE 64 - -#define IPX_OPEN 0 -#define IPX_CLOSE 1 -#define IPX_GETROUTE 2 -#define IPX_SEND 3 -#define IPX_LISTEN 4 -#define IPX_SCHEDULEEVENT 5 -#define IPX_CANCEL 6 -#define IPX_SCHEDULESPECIALEVENT 7 -#define IPX_GETINTERVALMARKER 8 -#define IPX_GETADDRESS 9 -#define IPX_RELINQUISH 10 - -#define PTYPE_UNKNOWN 0 -#define PTYPE_RIP 1 -#define PTYPE_ECHO 2 -#define PTYPE_ERROR 3 -#define PTYPE_IPX 4 -#define PTYPE_SPX 5 - -#pragma pack(1) - -typedef struct -{ - byte network[4]; - byte node[6]; - short socket; -} IPXaddr; - -struct sockaddr_ipx -{ - short sipx_family; - IPXaddr sipx_addr; - char sipx_zero[2]; -}; -#define sipx_port sipx_addr.socket - -typedef struct -{ - short checkSum; - short length; - byte transportControl; - byte type; - IPXaddr destination; - IPXaddr source; -} IPXheader; - -typedef struct ECBStructure -{ - struct ECBStructure *link; - unsigned short ESR_off; - unsigned short ESR_seg; - byte inUse; - byte completionCode; - short socket; - byte IPXWorkspace[4]; - byte driverWorkspace[12]; - byte immediateAddress[6]; - short fragCount; - short fragOff; - short fragSeg; - short fragSize; -} ECB; - -#pragma pack() - -typedef struct -{ - ECB ecb; - IPXheader header; - int sequence; - char data[NET_DATAGRAMSIZE]; -} ipx_lowmem_buffer_t; - -#define LOWMEMSIZE (100 * 1024) -#define LOWMEMSAVE 256 -#define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t)) -#define IPXSOCKBUFFERS 5 -#define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS) - -// each socket's socketbuffer 0 is used for sending, the others for listening - -typedef struct -{ - char reserved[LOWMEMSAVE]; - ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS]; -} ipx_lowmem_area_t; - - -static int ipxsocket[IPXSOCKETS]; -static ECB *readlist[IPXSOCKETS]; -static int sequence[IPXSOCKETS]; -static int handlesInUse; -static ipx_lowmem_area_t *lma; -static char *lowmem_buffer; -static int lowmem_bufseg; -static int lowmem_bufoff; -static unsigned short ipx_cs; -static unsigned short ipx_ip; -static int net_acceptsocket = -1; -static int net_controlsocket; - -static void IPX_PollProcedure(void); -static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure}; - -//============================================================================= - -static void IPX_GetLocalAddress(IPXaddr *addr) -{ - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_GETADDRESS; - regs.x.es = lowmem_bufseg; - regs.x.si = lowmem_bufoff; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - Q_memcpy(addr, lowmem_buffer, 10); -} - -//============================================================================= - -static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget) -{ - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_GETROUTE; - regs.x.es = lowmem_bufseg; - regs.x.si = lowmem_bufoff; - regs.x.di = lowmem_bufoff + sizeof(IPXaddr); - Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr)); - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - if (regs.h.al) - return -1; - Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6); - return 0; -} - -//============================================================================= - -static void IPX_ListenForPacket(ECB *ecb) -{ - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_LISTEN; - regs.x.es = ptr2real(ecb) >> 4; - regs.x.si = ptr2real(ecb) & 0xf; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); -} - -//============================================================================= - -static void IPX_RelinquishControl(void) -{ - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_RELINQUISH; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); -} - - -void IPX_PollProcedure(void) -{ - IPX_RelinquishControl(); - SchedulePollProcedure(&pollProcedure, 0.01); -} - -//============================================================================= - -static void ProcessReadyList(int s) -{ - int n; - ECB *ecb; - ECB *prev; - - for (n = 1; n < IPXSOCKBUFFERS; n++) - { - if (lma->socketbuffer[s][n].ecb.inUse == 0) - { - for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link) - { - if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence) - break; - prev = ecb; - } - if (ecb) - lma->socketbuffer[s][n].ecb.link = ecb; - else - lma->socketbuffer[s][n].ecb.link = NULL; - if (prev) - prev->link = &lma->socketbuffer[s][n].ecb; - else - readlist[s] = &lma->socketbuffer[s][n].ecb; - lma->socketbuffer[s][n].ecb.inUse = 0xff; - } - } -} - -//============================================================================= - -int IPX_Init(void) -{ - int s; - int n; - struct qsockaddr addr; - char *colon; - - if (COM_CheckParm ("-noipx")) - return -1; - - // find the IPX far call entry point - regs.x.ax = 0x7a00; - __dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)®s); - if (regs.h.al != 0xff) - { - Con_Printf("IPX not detected\n"); - return -1; - } - ipx_cs = regs.x.es; - ipx_ip = regs.x.di; - - // grab a chunk of memory down in DOS land - lowmem_buffer = dos_getmemory(LOWMEMSIZE); - if (!lowmem_buffer) - { - Con_Printf("IPX_Init: Not enough low memory\n"); - return -1; - } - lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf; - lowmem_bufseg = ptr2real(lowmem_buffer) >> 4; - - // init socket handles & buffers - handlesInUse = 0; - lma = (ipx_lowmem_area_t *)lowmem_buffer; - for (s = 0; s < IPXSOCKETS; s++) - { - ipxsocket[s] = 0; - for (n = 0; n < IPXSOCKBUFFERS; n++) - { - lma->socketbuffer[s][n].ecb.link = NULL; - lma->socketbuffer[s][n].ecb.ESR_off = 0; - lma->socketbuffer[s][n].ecb.ESR_seg = 0; - lma->socketbuffer[s][n].ecb.socket = 0; - lma->socketbuffer[s][n].ecb.inUse = 0xff; - lma->socketbuffer[s][n].ecb.completionCode = 0; - lma->socketbuffer[s][n].ecb.fragCount = 1; - lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf; - lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4; - lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; - } - } - - if ((net_controlsocket = IPX_OpenSocket (0)) == -1) - { - dos_freememory(lowmem_buffer); - Con_DPrintf ("IPX_Init: Unable to open control socket\n"); - return -1; - } - - SchedulePollProcedure(&pollProcedure, 0.01); - - IPX_GetSocketAddr (net_controlsocket, &addr); - Q_strcpy(my_ipx_address, IPX_AddrToString (&addr)); - colon = Q_strrchr (my_ipx_address, ':'); - if (colon) - *colon = 0; - - Con_Printf("IPX initialized\n"); - ipxAvailable = true; - return net_controlsocket; -} - -//============================================================================= - -void IPX_Shutdown(void) -{ - IPX_Listen (false); - IPX_CloseSocket (net_controlsocket); - dos_freememory(lowmem_buffer); -} - -//============================================================================= - -void IPX_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1) - Sys_Error ("IPX_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - IPX_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - -//============================================================================= - -int IPX_OpenSocket(int port) -{ - int handle; - int n; - unsigned short socket; - - if (handlesInUse == IPXSOCKETS) - return -1; - - // open the IPX socket - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_OPEN; - regs.h.al = 0; - regs.x.dx = htons(port); - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - if (regs.h.al == 0xfe) - { - Con_DPrintf("IPX_OpenSocket: all sockets in use\n"); - return -1; - } - if (regs.h.al == 0xff) - { - Con_DPrintf("IPX_OpenSocket: socket already open\n"); - return -1; - } - if (regs.h.al != 0) - { - Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al); - return -1; - } - socket = regs.x.dx; - -// grab a handle; fill in the ECBs, and get them listening - for (handle = 0; handle < IPXSOCKETS; handle++) - { - if (ipxsocket[handle] == 0) - { - ipxsocket[handle] = socket; - readlist[handle] = NULL; - sequence[handle] = 0; - for (n = 0; n < IPXSOCKBUFFERS; n ++) - { - lma->socketbuffer[handle][n].ecb.socket = socket; - lma->socketbuffer[handle][n].ecb.inUse = 0; - if (n) - IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb); - } - handlesInUse++; - return handle; - } - } - - // "this will NEVER happen" - Sys_Error("IPX_OpenSocket: handle allocation failed\n"); - return -1; -} - -//============================================================================= - -int IPX_CloseSocket(int handle) -{ - // if there's a send in progress, give it one last chance - if (lma->socketbuffer[handle][0].ecb.inUse != 0) - IPX_RelinquishControl(); - - // close the socket (all pending sends/received are cancelled) - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_CLOSE; - regs.x.dx = ipxsocket[handle]; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - - ipxsocket[handle] = 0; - handlesInUse--; - - return 0; -} - -//============================================================================= - -int IPX_Connect (int handle, struct qsockaddr *addr) -{ - IPXaddr ipxaddr; - - Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); - if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) - { - Con_Printf("Get Local Target failed\n"); - return -1; - } - - return 0; -} - -//============================================================================= - -int IPX_CheckNewConnections (void) -{ - int n; - - if (net_acceptsocket == -1) - return -1; - - for (n = 1; n < IPXSOCKBUFFERS; n ++) - if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0) - return net_acceptsocket; - return -1; -} - -//============================================================================= - -int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) -{ - ECB *ecb; - ipx_lowmem_buffer_t *rcvbuf; - int copylen; - - ProcessReadyList(handle); -tryagain: - if (readlist[handle] == NULL) - return 0; - ecb = readlist[handle]; - readlist[handle] = ecb->link; - - if (ecb->completionCode != 0) - { - Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode); - ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; - IPX_ListenForPacket(ecb); - goto tryagain; - } - - rcvbuf = (ipx_lowmem_buffer_t *)ecb; - - // copy the data up to the buffer - copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader)); - if (len < copylen) - Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen); - Q_memcpy(buf, rcvbuf->data, copylen); - - // fill in the addr if they want it - if (addr) - { - ((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE; - Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr)); - ((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0; - ((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0; - } - - // update the send ecb's immediate address - Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6); - - // get this ecb listening again - rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; - IPX_ListenForPacket(&rcvbuf->ecb); - return copylen; -} - -//============================================================================= - -int IPX_Broadcast (int handle, byte *buf, int len) -{ - struct sockaddr_ipx addr; - int ret; - - Q_memset(addr.sipx_addr.network, 0x00, 4); - Q_memset(addr.sipx_addr.node, 0xff, 6); - addr.sipx_port = htons(net_hostport); - Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6); - ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr); - return ret; -} - -//============================================================================= - -int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) -{ - // has the previous send completed? - while (lma->socketbuffer[handle][0].ecb.inUse != 0) - IPX_RelinquishControl(); - - switch (lma->socketbuffer[handle][0].ecb.completionCode) - { - case 0x00: // success - case 0xfc: // request cancelled - break; - - case 0xfd: // malformed packet - default: - Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode); - break; - - case 0xfe: // packet undeliverable - case 0xff: // unable to send packet - Con_Printf("IPX lost route, trying to re-establish\n"); - - // look for a new route - if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) - return -1; - - // re-send the one that failed - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_SEND; - regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; - regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - - // report that we did not send the current one - return 0; - } - - // ecb : length - lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len; - - // ipx header : type - lma->socketbuffer[handle][0].header.type = PTYPE_IPX; - - // ipx header : destination - Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); - - // sequence number - lma->socketbuffer[handle][0].sequence = sequence[handle]; - sequence[handle]++; - - // copy down the data - Q_memcpy(lma->socketbuffer[handle][0].data, buf, len); - - regs.x.cs = ipx_cs; - regs.x.ip = ipx_ip; - regs.x.bx = IPX_SEND; - regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; - regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; - __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); - - return len; -} - -//============================================================================= - -char *IPX_AddrToString (struct qsockaddr *addr) -{ - static char buf[28]; - - sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", - ((struct sockaddr_ipx *)addr)->sipx_addr.network[0], - ((struct sockaddr_ipx *)addr)->sipx_addr.network[1], - ((struct sockaddr_ipx *)addr)->sipx_addr.network[2], - ((struct sockaddr_ipx *)addr)->sipx_addr.network[3], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[0], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[1], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[2], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[3], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[4], - ((struct sockaddr_ipx *)addr)->sipx_addr.node[5], - ntohs(((struct sockaddr_ipx *)addr)->sipx_port) - ); - return buf; -} - -//============================================================================= - -int IPX_StringToAddr (char *string, struct qsockaddr *addr) -{ - int val; - char buf[3]; - - buf[2] = 0; - Q_memset(addr, 0, sizeof(struct qsockaddr)); - addr->sa_family = AF_NETWARE; - -#define DO(src,dest) \ - buf[0] = string[src]; \ - buf[1] = string[src + 1]; \ - if (sscanf (buf, "%x", &val) != 1) \ - return -1; \ - ((struct sockaddr_ipx *)addr)->sipx_addr.dest = val - - DO(0, network[0]); - DO(2, network[1]); - DO(4, network[2]); - DO(6, network[3]); - DO(9, node[0]); - DO(11, node[1]); - DO(13, node[2]); - DO(15, node[3]); - DO(17, node[4]); - DO(19, node[5]); -#undef DO - - sscanf (&string[22], "%u", &val); - ((struct sockaddr_ipx *)addr)->sipx_port = htons(val); - - return 0; -} - -//============================================================================= - -int IPX_GetSocketAddr (int handle, struct qsockaddr *addr) -{ - Q_memset(addr, 0, sizeof(struct qsockaddr)); - addr->sa_family = AF_NETWARE; - IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr); - ((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle]; - return 0; -} - -//============================================================================= - -int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name) -{ - Q_strcpy(name, IPX_AddrToString(addr)); - return 0; -} - -//============================================================================= - -int IPX_GetAddrFromName (char *name, struct qsockaddr *addr) -{ - int n; - char buf[32]; - - n = Q_strlen(name); - - if (n == 12) - { - sprintf(buf, "00000000:%s:%u", name, net_hostport); - return IPX_StringToAddr (buf, addr); - } - if (n == 21) - { - sprintf(buf, "%s:%u", name, net_hostport); - return IPX_StringToAddr (buf, addr); - } - if (n > 21 && n <= 27) - return IPX_StringToAddr (name, addr); - - return -1; -} - -//============================================================================= - -int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10)) - return -1; - - if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port) - return 1; - - return 0; -} - -//============================================================================= - -int IPX_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_ipx *)addr)->sipx_port); -} - - -int IPX_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_ipx *)addr)->sipx_port = htons(port); - return 0; -} - -//============================================================================= +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_ipx.c + +#include +#include +#include + +#include "quakedef.h" +#include "dosisms.h" +#include "net_ipx.h" + +#define EIO 5 /* I/O error */ + +#define AF_NETWARE 64 + +#define IPX_OPEN 0 +#define IPX_CLOSE 1 +#define IPX_GETROUTE 2 +#define IPX_SEND 3 +#define IPX_LISTEN 4 +#define IPX_SCHEDULEEVENT 5 +#define IPX_CANCEL 6 +#define IPX_SCHEDULESPECIALEVENT 7 +#define IPX_GETINTERVALMARKER 8 +#define IPX_GETADDRESS 9 +#define IPX_RELINQUISH 10 + +#define PTYPE_UNKNOWN 0 +#define PTYPE_RIP 1 +#define PTYPE_ECHO 2 +#define PTYPE_ERROR 3 +#define PTYPE_IPX 4 +#define PTYPE_SPX 5 + +#pragma pack(1) + +typedef struct +{ + byte network[4]; + byte node[6]; + short socket; +} IPXaddr; + +struct sockaddr_ipx +{ + short sipx_family; + IPXaddr sipx_addr; + char sipx_zero[2]; +}; +#define sipx_port sipx_addr.socket + +typedef struct +{ + short checkSum; + short length; + byte transportControl; + byte type; + IPXaddr destination; + IPXaddr source; +} IPXheader; + +typedef struct ECBStructure +{ + struct ECBStructure *link; + unsigned short ESR_off; + unsigned short ESR_seg; + byte inUse; + byte completionCode; + short socket; + byte IPXWorkspace[4]; + byte driverWorkspace[12]; + byte immediateAddress[6]; + short fragCount; + short fragOff; + short fragSeg; + short fragSize; +} ECB; + +#pragma pack() + +typedef struct +{ + ECB ecb; + IPXheader header; + int sequence; + char data[NET_DATAGRAMSIZE]; +} ipx_lowmem_buffer_t; + +#define LOWMEMSIZE (100 * 1024) +#define LOWMEMSAVE 256 +#define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t)) +#define IPXSOCKBUFFERS 5 +#define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS) + +// each socket's socketbuffer 0 is used for sending, the others for listening + +typedef struct +{ + char reserved[LOWMEMSAVE]; + ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS]; +} ipx_lowmem_area_t; + + +static int ipxsocket[IPXSOCKETS]; +static ECB *readlist[IPXSOCKETS]; +static int sequence[IPXSOCKETS]; +static int handlesInUse; +static ipx_lowmem_area_t *lma; +static char *lowmem_buffer; +static int lowmem_bufseg; +static int lowmem_bufoff; +static unsigned short ipx_cs; +static unsigned short ipx_ip; +static int net_acceptsocket = -1; +static int net_controlsocket; + +static void IPX_PollProcedure(void); +static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure}; + +//============================================================================= + +static void IPX_GetLocalAddress(IPXaddr *addr) +{ + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_GETADDRESS; + regs.x.es = lowmem_bufseg; + regs.x.si = lowmem_bufoff; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + Q_memcpy(addr, lowmem_buffer, 10); +} + +//============================================================================= + +static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget) +{ + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_GETROUTE; + regs.x.es = lowmem_bufseg; + regs.x.si = lowmem_bufoff; + regs.x.di = lowmem_bufoff + sizeof(IPXaddr); + Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr)); + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + if (regs.h.al) + return -1; + Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6); + return 0; +} + +//============================================================================= + +static void IPX_ListenForPacket(ECB *ecb) +{ + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_LISTEN; + regs.x.es = ptr2real(ecb) >> 4; + regs.x.si = ptr2real(ecb) & 0xf; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); +} + +//============================================================================= + +static void IPX_RelinquishControl(void) +{ + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_RELINQUISH; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); +} + + +void IPX_PollProcedure(void) +{ + IPX_RelinquishControl(); + SchedulePollProcedure(&pollProcedure, 0.01); +} + +//============================================================================= + +static void ProcessReadyList(int s) +{ + int n; + ECB *ecb; + ECB *prev; + + for (n = 1; n < IPXSOCKBUFFERS; n++) + { + if (lma->socketbuffer[s][n].ecb.inUse == 0) + { + for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link) + { + if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence) + break; + prev = ecb; + } + if (ecb) + lma->socketbuffer[s][n].ecb.link = ecb; + else + lma->socketbuffer[s][n].ecb.link = NULL; + if (prev) + prev->link = &lma->socketbuffer[s][n].ecb; + else + readlist[s] = &lma->socketbuffer[s][n].ecb; + lma->socketbuffer[s][n].ecb.inUse = 0xff; + } + } +} + +//============================================================================= + +int IPX_Init(void) +{ + int s; + int n; + struct qsockaddr addr; + char *colon; + + if (COM_CheckParm ("-noipx")) + return -1; + + // find the IPX far call entry point + regs.x.ax = 0x7a00; + __dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)®s); + if (regs.h.al != 0xff) + { + Con_Printf("IPX not detected\n"); + return -1; + } + ipx_cs = regs.x.es; + ipx_ip = regs.x.di; + + // grab a chunk of memory down in DOS land + lowmem_buffer = dos_getmemory(LOWMEMSIZE); + if (!lowmem_buffer) + { + Con_Printf("IPX_Init: Not enough low memory\n"); + return -1; + } + lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf; + lowmem_bufseg = ptr2real(lowmem_buffer) >> 4; + + // init socket handles & buffers + handlesInUse = 0; + lma = (ipx_lowmem_area_t *)lowmem_buffer; + for (s = 0; s < IPXSOCKETS; s++) + { + ipxsocket[s] = 0; + for (n = 0; n < IPXSOCKBUFFERS; n++) + { + lma->socketbuffer[s][n].ecb.link = NULL; + lma->socketbuffer[s][n].ecb.ESR_off = 0; + lma->socketbuffer[s][n].ecb.ESR_seg = 0; + lma->socketbuffer[s][n].ecb.socket = 0; + lma->socketbuffer[s][n].ecb.inUse = 0xff; + lma->socketbuffer[s][n].ecb.completionCode = 0; + lma->socketbuffer[s][n].ecb.fragCount = 1; + lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf; + lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4; + lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; + } + } + + if ((net_controlsocket = IPX_OpenSocket (0)) == -1) + { + dos_freememory(lowmem_buffer); + Con_DPrintf ("IPX_Init: Unable to open control socket\n"); + return -1; + } + + SchedulePollProcedure(&pollProcedure, 0.01); + + IPX_GetSocketAddr (net_controlsocket, &addr); + Q_strcpy(my_ipx_address, IPX_AddrToString (&addr)); + colon = Q_strrchr (my_ipx_address, ':'); + if (colon) + *colon = 0; + + Con_Printf("IPX initialized\n"); + ipxAvailable = true; + return net_controlsocket; +} + +//============================================================================= + +void IPX_Shutdown(void) +{ + IPX_Listen (false); + IPX_CloseSocket (net_controlsocket); + dos_freememory(lowmem_buffer); +} + +//============================================================================= + +void IPX_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1) + Sys_Error ("IPX_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + IPX_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int IPX_OpenSocket(int port) +{ + int handle; + int n; + unsigned short socket; + + if (handlesInUse == IPXSOCKETS) + return -1; + + // open the IPX socket + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_OPEN; + regs.h.al = 0; + regs.x.dx = htons(port); + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + if (regs.h.al == 0xfe) + { + Con_DPrintf("IPX_OpenSocket: all sockets in use\n"); + return -1; + } + if (regs.h.al == 0xff) + { + Con_DPrintf("IPX_OpenSocket: socket already open\n"); + return -1; + } + if (regs.h.al != 0) + { + Con_DPrintf("IPX_OpenSocket: error %02x\n", regs.h.al); + return -1; + } + socket = regs.x.dx; + +// grab a handle; fill in the ECBs, and get them listening + for (handle = 0; handle < IPXSOCKETS; handle++) + { + if (ipxsocket[handle] == 0) + { + ipxsocket[handle] = socket; + readlist[handle] = NULL; + sequence[handle] = 0; + for (n = 0; n < IPXSOCKBUFFERS; n ++) + { + lma->socketbuffer[handle][n].ecb.socket = socket; + lma->socketbuffer[handle][n].ecb.inUse = 0; + if (n) + IPX_ListenForPacket(&lma->socketbuffer[handle][n].ecb); + } + handlesInUse++; + return handle; + } + } + + // "this will NEVER happen" + Sys_Error("IPX_OpenSocket: handle allocation failed\n"); + return -1; +} + +//============================================================================= + +int IPX_CloseSocket(int handle) +{ + // if there's a send in progress, give it one last chance + if (lma->socketbuffer[handle][0].ecb.inUse != 0) + IPX_RelinquishControl(); + + // close the socket (all pending sends/received are cancelled) + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_CLOSE; + regs.x.dx = ipxsocket[handle]; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + + ipxsocket[handle] = 0; + handlesInUse--; + + return 0; +} + +//============================================================================= + +int IPX_Connect (int handle, struct qsockaddr *addr) +{ + IPXaddr ipxaddr; + + Q_memcpy(&ipxaddr, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); + if (IPX_GetLocalTarget(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) + { + Con_Printf("Get Local Target failed\n"); + return -1; + } + + return 0; +} + +//============================================================================= + +int IPX_CheckNewConnections (void) +{ + int n; + + if (net_acceptsocket == -1) + return -1; + + for (n = 1; n < IPXSOCKBUFFERS; n ++) + if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0) + return net_acceptsocket; + return -1; +} + +//============================================================================= + +int IPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) +{ + ECB *ecb; + ipx_lowmem_buffer_t *rcvbuf; + int copylen; + + ProcessReadyList(handle); +tryagain: + if (readlist[handle] == NULL) + return 0; + ecb = readlist[handle]; + readlist[handle] = ecb->link; + + if (ecb->completionCode != 0) + { + Con_Printf("Warning: IPX_Read error %02x\n", ecb->completionCode); + ecb->fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; + IPX_ListenForPacket(ecb); + goto tryagain; + } + + rcvbuf = (ipx_lowmem_buffer_t *)ecb; + + // copy the data up to the buffer + copylen = ntohs(rcvbuf->header.length) - (sizeof(int) + sizeof(IPXheader)); + if (len < copylen) + Sys_Error("IPX_Read: buffer too small (%d vs %d)\n", len, copylen); + Q_memcpy(buf, rcvbuf->data, copylen); + + // fill in the addr if they want it + if (addr) + { + ((struct sockaddr_ipx *)addr)->sipx_family = AF_NETWARE; + Q_memcpy(&((struct sockaddr_ipx *)addr)->sipx_addr, rcvbuf->header.source.network, sizeof(IPXaddr)); + ((struct sockaddr_ipx *)addr)->sipx_zero[0] = 0; + ((struct sockaddr_ipx *)addr)->sipx_zero[1] = 0; + } + + // update the send ecb's immediate address + Q_memcpy(lma->socketbuffer[handle][0].ecb.immediateAddress, rcvbuf->ecb.immediateAddress, 6); + + // get this ecb listening again + rcvbuf->ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE; + IPX_ListenForPacket(&rcvbuf->ecb); + return copylen; +} + +//============================================================================= + +int IPX_Broadcast (int handle, byte *buf, int len) +{ + struct sockaddr_ipx addr; + int ret; + + Q_memset(addr.sipx_addr.network, 0x00, 4); + Q_memset(addr.sipx_addr.node, 0xff, 6); + addr.sipx_port = htons(net_hostport); + Q_memset(lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6); + ret = IPX_Write (handle, buf, len, (struct qsockaddr *)&addr); + return ret; +} + +//============================================================================= + +int IPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) +{ + // has the previous send completed? + while (lma->socketbuffer[handle][0].ecb.inUse != 0) + IPX_RelinquishControl(); + + switch (lma->socketbuffer[handle][0].ecb.completionCode) + { + case 0x00: // success + case 0xfc: // request cancelled + break; + + case 0xfd: // malformed packet + default: + Con_Printf("IPX driver send failure: %02x\n", lma->socketbuffer[handle][0].ecb.completionCode); + break; + + case 0xfe: // packet undeliverable + case 0xff: // unable to send packet + Con_Printf("IPX lost route, trying to re-establish\n"); + + // look for a new route + if (IPX_GetLocalTarget (&lma->socketbuffer[handle][0].header.destination, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) + return -1; + + // re-send the one that failed + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_SEND; + regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; + regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + + // report that we did not send the current one + return 0; + } + + // ecb : length + lma->socketbuffer[handle][0].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + len; + + // ipx header : type + lma->socketbuffer[handle][0].header.type = PTYPE_IPX; + + // ipx header : destination + Q_memcpy(&lma->socketbuffer[handle][0].header.destination, &((struct sockaddr_ipx *)addr)->sipx_addr, sizeof(IPXaddr)); + + // sequence number + lma->socketbuffer[handle][0].sequence = sequence[handle]; + sequence[handle]++; + + // copy down the data + Q_memcpy(lma->socketbuffer[handle][0].data, buf, len); + + regs.x.cs = ipx_cs; + regs.x.ip = ipx_ip; + regs.x.bx = IPX_SEND; + regs.x.es = ptr2real(&lma->socketbuffer[handle][0].ecb) >> 4; + regs.x.si = ptr2real(&lma->socketbuffer[handle][0].ecb) & 0xf; + __dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)®s); + + return len; +} + +//============================================================================= + +char *IPX_AddrToString (struct qsockaddr *addr) +{ + static char buf[28]; + + sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", + ((struct sockaddr_ipx *)addr)->sipx_addr.network[0], + ((struct sockaddr_ipx *)addr)->sipx_addr.network[1], + ((struct sockaddr_ipx *)addr)->sipx_addr.network[2], + ((struct sockaddr_ipx *)addr)->sipx_addr.network[3], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[0], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[1], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[2], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[3], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[4], + ((struct sockaddr_ipx *)addr)->sipx_addr.node[5], + ntohs(((struct sockaddr_ipx *)addr)->sipx_port) + ); + return buf; +} + +//============================================================================= + +int IPX_StringToAddr (char *string, struct qsockaddr *addr) +{ + int val; + char buf[3]; + + buf[2] = 0; + Q_memset(addr, 0, sizeof(struct qsockaddr)); + addr->sa_family = AF_NETWARE; + +#define DO(src,dest) \ + buf[0] = string[src]; \ + buf[1] = string[src + 1]; \ + if (sscanf (buf, "%x", &val) != 1) \ + return -1; \ + ((struct sockaddr_ipx *)addr)->sipx_addr.dest = val + + DO(0, network[0]); + DO(2, network[1]); + DO(4, network[2]); + DO(6, network[3]); + DO(9, node[0]); + DO(11, node[1]); + DO(13, node[2]); + DO(15, node[3]); + DO(17, node[4]); + DO(19, node[5]); +#undef DO + + sscanf (&string[22], "%u", &val); + ((struct sockaddr_ipx *)addr)->sipx_port = htons(val); + + return 0; +} + +//============================================================================= + +int IPX_GetSocketAddr (int handle, struct qsockaddr *addr) +{ + Q_memset(addr, 0, sizeof(struct qsockaddr)); + addr->sa_family = AF_NETWARE; + IPX_GetLocalAddress(&((struct sockaddr_ipx *)addr)->sipx_addr); + ((struct sockaddr_ipx *)addr)->sipx_port = ipxsocket[handle]; + return 0; +} + +//============================================================================= + +int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + Q_strcpy(name, IPX_AddrToString(addr)); + return 0; +} + +//============================================================================= + +int IPX_GetAddrFromName (char *name, struct qsockaddr *addr) +{ + int n; + char buf[32]; + + n = Q_strlen(name); + + if (n == 12) + { + sprintf(buf, "00000000:%s:%u", name, net_hostport); + return IPX_StringToAddr (buf, addr); + } + if (n == 21) + { + sprintf(buf, "%s:%u", name, net_hostport); + return IPX_StringToAddr (buf, addr); + } + if (n > 21 && n <= 27) + return IPX_StringToAddr (name, addr); + + return -1; +} + +//============================================================================= + +int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if(Q_memcmp(&((struct sockaddr_ipx *)addr1)->sipx_addr, &((struct sockaddr_ipx *)addr2)->sipx_addr, 10)) + return -1; + + if (((struct sockaddr_ipx *)addr1)->sipx_port != ((struct sockaddr_ipx *)addr2)->sipx_port) + return 1; + + return 0; +} + +//============================================================================= + +int IPX_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_ipx *)addr)->sipx_port); +} + + +int IPX_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_ipx *)addr)->sipx_port = htons(port); + return 0; +} + +//============================================================================= diff --git a/WinQuake/net_ipx.h b/WinQuake/net_ipx.h index 464fec4..de39f7e 100644 --- a/WinQuake/net_ipx.h +++ b/WinQuake/net_ipx.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_ipx.h - -int IPX_Init (void); -void IPX_Shutdown (void); -void IPX_Listen (qboolean state); -int IPX_OpenSocket (int port); -int IPX_CloseSocket (int socket); -int IPX_Connect (int socket, struct qsockaddr *addr); -int IPX_CheckNewConnections (void); -int IPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int IPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int IPX_Broadcast (int socket, byte *buf, int len); -char *IPX_AddrToString (struct qsockaddr *addr); -int IPX_StringToAddr (char *string, struct qsockaddr *addr); -int IPX_GetSocketAddr (int socket, struct qsockaddr *addr); -int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name); -int IPX_GetAddrFromName (char *name, struct qsockaddr *addr); -int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int IPX_GetSocketPort (struct qsockaddr *addr); -int IPX_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_ipx.h + +int IPX_Init (void); +void IPX_Shutdown (void); +void IPX_Listen (qboolean state); +int IPX_OpenSocket (int port); +int IPX_CloseSocket (int socket); +int IPX_Connect (int socket, struct qsockaddr *addr); +int IPX_CheckNewConnections (void); +int IPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int IPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int IPX_Broadcast (int socket, byte *buf, int len); +char *IPX_AddrToString (struct qsockaddr *addr); +int IPX_StringToAddr (char *string, struct qsockaddr *addr); +int IPX_GetSocketAddr (int socket, struct qsockaddr *addr); +int IPX_GetNameFromAddr (struct qsockaddr *addr, char *name); +int IPX_GetAddrFromName (char *name, struct qsockaddr *addr); +int IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int IPX_GetSocketPort (struct qsockaddr *addr); +int IPX_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/net_loop.c b/WinQuake/net_loop.c index 35aa370..4a2719e 100644 --- a/WinQuake/net_loop.c +++ b/WinQuake/net_loop.c @@ -1,245 +1,245 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_loop.c - -#include "quakedef.h" -#include "net_loop.h" - -qboolean localconnectpending = false; -qsocket_t *loop_client = NULL; -qsocket_t *loop_server = NULL; - -int Loop_Init (void) -{ - if (cls.state == ca_dedicated) - return -1; - return 0; -} - - -void Loop_Shutdown (void) -{ -} - - -void Loop_Listen (qboolean state) -{ -} - - -void Loop_SearchForHosts (qboolean xmit) -{ - if (!sv.active) - return; - - hostCacheCount = 1; - if (Q_strcmp(hostname.string, "UNNAMED") == 0) - Q_strcpy(hostcache[0].name, "local"); - else - Q_strcpy(hostcache[0].name, hostname.string); - Q_strcpy(hostcache[0].map, sv.name); - hostcache[0].users = net_activeconnections; - hostcache[0].maxusers = svs.maxclients; - hostcache[0].driver = net_driverlevel; - Q_strcpy(hostcache[0].cname, "local"); -} - - -qsocket_t *Loop_Connect (char *host) -{ - if (Q_strcmp(host,"local") != 0) - return NULL; - - localconnectpending = true; - - if (!loop_client) - { - if ((loop_client = NET_NewQSocket ()) == NULL) - { - Con_Printf("Loop_Connect: no qsocket available\n"); - return NULL; - } - Q_strcpy (loop_client->address, "localhost"); - } - loop_client->receiveMessageLength = 0; - loop_client->sendMessageLength = 0; - loop_client->canSend = true; - - if (!loop_server) - { - if ((loop_server = NET_NewQSocket ()) == NULL) - { - Con_Printf("Loop_Connect: no qsocket available\n"); - return NULL; - } - Q_strcpy (loop_server->address, "LOCAL"); - } - loop_server->receiveMessageLength = 0; - loop_server->sendMessageLength = 0; - loop_server->canSend = true; - - loop_client->driverdata = (void *)loop_server; - loop_server->driverdata = (void *)loop_client; - - return loop_client; -} - - -qsocket_t *Loop_CheckNewConnections (void) -{ - if (!localconnectpending) - return NULL; - - localconnectpending = false; - loop_server->sendMessageLength = 0; - loop_server->receiveMessageLength = 0; - loop_server->canSend = true; - loop_client->sendMessageLength = 0; - loop_client->receiveMessageLength = 0; - loop_client->canSend = true; - return loop_server; -} - - -static int IntAlign(int value) -{ - return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1)); -} - - -int Loop_GetMessage (qsocket_t *sock) -{ - int ret; - int length; - - if (sock->receiveMessageLength == 0) - return 0; - - ret = sock->receiveMessage[0]; - length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8); - // alignment byte skipped here - SZ_Clear (&net_message); - SZ_Write (&net_message, &sock->receiveMessage[4], length); - - length = IntAlign(length + 4); - sock->receiveMessageLength -= length; - - if (sock->receiveMessageLength) - Q_memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength); - - if (sock->driverdata && ret == 1) - ((qsocket_t *)sock->driverdata)->canSend = true; - - return ret; -} - - -int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - byte *buffer; - int *bufferLength; - - if (!sock->driverdata) - return -1; - - bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; - - if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE) - Sys_Error("Loop_SendMessage: overflow\n"); - - buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; - - // message type - *buffer++ = 1; - - // length - *buffer++ = data->cursize & 0xff; - *buffer++ = data->cursize >> 8; - - // align - buffer++; - - // message - Q_memcpy(buffer, data->data, data->cursize); - *bufferLength = IntAlign(*bufferLength + data->cursize + 4); - - sock->canSend = false; - return 1; -} - - -int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - byte *buffer; - int *bufferLength; - - if (!sock->driverdata) - return -1; - - bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; - - if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE) - return 0; - - buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; - - // message type - *buffer++ = 2; - - // length - *buffer++ = data->cursize & 0xff; - *buffer++ = data->cursize >> 8; - - // align - buffer++; - - // message - Q_memcpy(buffer, data->data, data->cursize); - *bufferLength = IntAlign(*bufferLength + data->cursize + 4); - return 1; -} - - -qboolean Loop_CanSendMessage (qsocket_t *sock) -{ - if (!sock->driverdata) - return false; - return sock->canSend; -} - - -qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock) -{ - return true; -} - - -void Loop_Close (qsocket_t *sock) -{ - if (sock->driverdata) - ((qsocket_t *)sock->driverdata)->driverdata = NULL; - sock->receiveMessageLength = 0; - sock->sendMessageLength = 0; - sock->canSend = true; - if (sock == loop_client) - loop_client = NULL; - else - loop_server = NULL; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_loop.c + +#include "quakedef.h" +#include "net_loop.h" + +qboolean localconnectpending = false; +qsocket_t *loop_client = NULL; +qsocket_t *loop_server = NULL; + +int Loop_Init (void) +{ + if (cls.state == ca_dedicated) + return -1; + return 0; +} + + +void Loop_Shutdown (void) +{ +} + + +void Loop_Listen (qboolean state) +{ +} + + +void Loop_SearchForHosts (qboolean xmit) +{ + if (!sv.active) + return; + + hostCacheCount = 1; + if (Q_strcmp(hostname.string, "UNNAMED") == 0) + Q_strcpy(hostcache[0].name, "local"); + else + Q_strcpy(hostcache[0].name, hostname.string); + Q_strcpy(hostcache[0].map, sv.name); + hostcache[0].users = net_activeconnections; + hostcache[0].maxusers = svs.maxclients; + hostcache[0].driver = net_driverlevel; + Q_strcpy(hostcache[0].cname, "local"); +} + + +qsocket_t *Loop_Connect (char *host) +{ + if (Q_strcmp(host,"local") != 0) + return NULL; + + localconnectpending = true; + + if (!loop_client) + { + if ((loop_client = NET_NewQSocket ()) == NULL) + { + Con_Printf("Loop_Connect: no qsocket available\n"); + return NULL; + } + Q_strcpy (loop_client->address, "localhost"); + } + loop_client->receiveMessageLength = 0; + loop_client->sendMessageLength = 0; + loop_client->canSend = true; + + if (!loop_server) + { + if ((loop_server = NET_NewQSocket ()) == NULL) + { + Con_Printf("Loop_Connect: no qsocket available\n"); + return NULL; + } + Q_strcpy (loop_server->address, "LOCAL"); + } + loop_server->receiveMessageLength = 0; + loop_server->sendMessageLength = 0; + loop_server->canSend = true; + + loop_client->driverdata = (void *)loop_server; + loop_server->driverdata = (void *)loop_client; + + return loop_client; +} + + +qsocket_t *Loop_CheckNewConnections (void) +{ + if (!localconnectpending) + return NULL; + + localconnectpending = false; + loop_server->sendMessageLength = 0; + loop_server->receiveMessageLength = 0; + loop_server->canSend = true; + loop_client->sendMessageLength = 0; + loop_client->receiveMessageLength = 0; + loop_client->canSend = true; + return loop_server; +} + + +static int IntAlign(int value) +{ + return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1)); +} + + +int Loop_GetMessage (qsocket_t *sock) +{ + int ret; + int length; + + if (sock->receiveMessageLength == 0) + return 0; + + ret = sock->receiveMessage[0]; + length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8); + // alignment byte skipped here + SZ_Clear (&net_message); + SZ_Write (&net_message, &sock->receiveMessage[4], length); + + length = IntAlign(length + 4); + sock->receiveMessageLength -= length; + + if (sock->receiveMessageLength) + Q_memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength); + + if (sock->driverdata && ret == 1) + ((qsocket_t *)sock->driverdata)->canSend = true; + + return ret; +} + + +int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + byte *buffer; + int *bufferLength; + + if (!sock->driverdata) + return -1; + + bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; + + if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE) + Sys_Error("Loop_SendMessage: overflow\n"); + + buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; + + // message type + *buffer++ = 1; + + // length + *buffer++ = data->cursize & 0xff; + *buffer++ = data->cursize >> 8; + + // align + buffer++; + + // message + Q_memcpy(buffer, data->data, data->cursize); + *bufferLength = IntAlign(*bufferLength + data->cursize + 4); + + sock->canSend = false; + return 1; +} + + +int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) +{ + byte *buffer; + int *bufferLength; + + if (!sock->driverdata) + return -1; + + bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; + + if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE) + return 0; + + buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; + + // message type + *buffer++ = 2; + + // length + *buffer++ = data->cursize & 0xff; + *buffer++ = data->cursize >> 8; + + // align + buffer++; + + // message + Q_memcpy(buffer, data->data, data->cursize); + *bufferLength = IntAlign(*bufferLength + data->cursize + 4); + return 1; +} + + +qboolean Loop_CanSendMessage (qsocket_t *sock) +{ + if (!sock->driverdata) + return false; + return sock->canSend; +} + + +qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock) +{ + return true; +} + + +void Loop_Close (qsocket_t *sock) +{ + if (sock->driverdata) + ((qsocket_t *)sock->driverdata)->driverdata = NULL; + sock->receiveMessageLength = 0; + sock->sendMessageLength = 0; + sock->canSend = true; + if (sock == loop_client) + loop_client = NULL; + else + loop_server = NULL; +} diff --git a/WinQuake/net_loop.h b/WinQuake/net_loop.h index 90cdb2c..210f40d 100644 --- a/WinQuake/net_loop.h +++ b/WinQuake/net_loop.h @@ -1,33 +1,33 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_loop.h - -int Loop_Init (void); -void Loop_Listen (qboolean state); -void Loop_SearchForHosts (qboolean xmit); -qsocket_t *Loop_Connect (char *host); -qsocket_t *Loop_CheckNewConnections (void); -int Loop_GetMessage (qsocket_t *sock); -int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data); -int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Loop_CanSendMessage (qsocket_t *sock); -qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); -void Loop_Close (qsocket_t *sock); -void Loop_Shutdown (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_loop.h + +int Loop_Init (void); +void Loop_Listen (qboolean state); +void Loop_SearchForHosts (qboolean xmit); +qsocket_t *Loop_Connect (char *host); +qsocket_t *Loop_CheckNewConnections (void); +int Loop_GetMessage (qsocket_t *sock); +int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data); +int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); +qboolean Loop_CanSendMessage (qsocket_t *sock); +qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); +void Loop_Close (qsocket_t *sock); +void Loop_Shutdown (void); diff --git a/WinQuake/net_main.c b/WinQuake/net_main.c index 5f5d2cf..4836ab5 100644 --- a/WinQuake/net_main.c +++ b/WinQuake/net_main.c @@ -1,997 +1,997 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_main.c - -#include "quakedef.h" -#include "net_vcr.h" - -qsocket_t *net_activeSockets = NULL; -qsocket_t *net_freeSockets = NULL; -int net_numsockets = 0; - -qboolean serialAvailable = false; -qboolean ipxAvailable = false; -qboolean tcpipAvailable = false; - -int net_hostport; -int DEFAULTnet_hostport = 26000; - -char my_ipx_address[NET_NAMELEN]; -char my_tcpip_address[NET_NAMELEN]; - -void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem); -void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem); -void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); -void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); - -static qboolean listening = false; - -qboolean slistInProgress = false; -qboolean slistSilent = false; -qboolean slistLocal = true; -static double slistStartTime; -static int slistLastShown; - -static void Slist_Send(void); -static void Slist_Poll(void); -PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send}; -PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll}; - - -sizebuf_t net_message; -int net_activeconnections = 0; - -int messagesSent = 0; -int messagesReceived = 0; -int unreliableMessagesSent = 0; -int unreliableMessagesReceived = 0; - -cvar_t net_messagetimeout = {"net_messagetimeout","300"}; -cvar_t hostname = {"hostname", "UNNAMED"}; - -qboolean configRestored = false; -cvar_t config_com_port = {"_config_com_port", "0x3f8", true}; -cvar_t config_com_irq = {"_config_com_irq", "4", true}; -cvar_t config_com_baud = {"_config_com_baud", "57600", true}; -cvar_t config_com_modem = {"_config_com_modem", "1", true}; -cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true}; -cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true}; -cvar_t config_modem_init = {"_config_modem_init", "", true}; -cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true}; - -#ifdef IDGODS -cvar_t idgods = {"idgods", "0"}; -#endif - -int vcrFile = -1; -qboolean recording = false; - -// these two macros are to make the code more readable -#define sfunc net_drivers[sock->driver] -#define dfunc net_drivers[net_driverlevel] - -int net_driverlevel; - - -double net_time; - -double SetNetTime(void) -{ - net_time = Sys_FloatTime(); - return net_time; -} - - -/* -=================== -NET_NewQSocket - -Called by drivers when a new communications endpoint is required -The sequence and buffer fields will be filled in properly -=================== -*/ -qsocket_t *NET_NewQSocket (void) -{ - qsocket_t *sock; - - if (net_freeSockets == NULL) - return NULL; - - if (net_activeconnections >= svs.maxclients) - return NULL; - - // get one from free list - sock = net_freeSockets; - net_freeSockets = sock->next; - - // add it to active list - sock->next = net_activeSockets; - net_activeSockets = sock; - - sock->disconnected = false; - sock->connecttime = net_time; - Q_strcpy (sock->address,"UNSET ADDRESS"); - sock->driver = net_driverlevel; - sock->socket = 0; - sock->driverdata = NULL; - sock->canSend = true; - sock->sendNext = false; - sock->lastMessageTime = net_time; - sock->ackSequence = 0; - sock->sendSequence = 0; - sock->unreliableSendSequence = 0; - sock->sendMessageLength = 0; - sock->receiveSequence = 0; - sock->unreliableReceiveSequence = 0; - sock->receiveMessageLength = 0; - - return sock; -} - - -void NET_FreeQSocket(qsocket_t *sock) -{ - qsocket_t *s; - - // remove it from active list - if (sock == net_activeSockets) - net_activeSockets = net_activeSockets->next; - else - { - for (s = net_activeSockets; s; s = s->next) - if (s->next == sock) - { - s->next = sock->next; - break; - } - if (!s) - Sys_Error ("NET_FreeQSocket: not active\n"); - } - - // add it to free list - sock->next = net_freeSockets; - net_freeSockets = sock; - sock->disconnected = true; -} - - -static void NET_Listen_f (void) -{ - if (Cmd_Argc () != 2) - { - Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0); - return; - } - - listening = Q_atoi(Cmd_Argv(1)) ? true : false; - - for (net_driverlevel=0 ; net_driverlevel svs.maxclientslimit) - { - n = svs.maxclientslimit; - Con_Printf ("\"maxplayers\" set to \"%u\"\n", n); - } - - if ((n == 1) && listening) - Cbuf_AddText ("listen 0\n"); - - if ((n > 1) && (!listening)) - Cbuf_AddText ("listen 1\n"); - - svs.maxclients = n; - if (n == 1) - Cvar_Set ("deathmatch", "0"); - else - Cvar_Set ("deathmatch", "1"); -} - - -static void NET_Port_f (void) -{ - int n; - - if (Cmd_Argc () != 2) - { - Con_Printf ("\"port\" is \"%u\"\n", net_hostport); - return; - } - - n = Q_atoi(Cmd_Argv(1)); - if (n < 1 || n > 65534) - { - Con_Printf ("Bad value, must be between 1 and 65534\n"); - return; - } - - DEFAULTnet_hostport = n; - net_hostport = n; - - if (listening) - { - // force a change to the new port - Cbuf_AddText ("listen 0\n"); - Cbuf_AddText ("listen 1\n"); - } -} - - -static void PrintSlistHeader(void) -{ - Con_Printf("Server Map Users\n"); - Con_Printf("--------------- --------------- -----\n"); - slistLastShown = 0; -} - - -static void PrintSlist(void) -{ - int n; - - for (n = slistLastShown; n < hostCacheCount; n++) - { - if (hostcache[n].maxusers) - Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); - else - Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); - } - slistLastShown = n; -} - - -static void PrintSlistTrailer(void) -{ - if (hostCacheCount) - Con_Printf("== end list ==\n\n"); - else - Con_Printf("No Quake servers found.\n\n"); -} - - -void NET_Slist_f (void) -{ - if (slistInProgress) - return; - - if (! slistSilent) - { - Con_Printf("Looking for Quake servers...\n"); - PrintSlistHeader(); - } - - slistInProgress = true; - slistStartTime = Sys_FloatTime(); - - SchedulePollProcedure(&slistSendProcedure, 0.0); - SchedulePollProcedure(&slistPollProcedure, 0.1); - - hostCacheCount = 0; -} - - -static void Slist_Send(void) -{ - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - dfunc.SearchForHosts (true); - } - - if ((Sys_FloatTime() - slistStartTime) < 0.5) - SchedulePollProcedure(&slistSendProcedure, 0.75); -} - - -static void Slist_Poll(void) -{ - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - dfunc.SearchForHosts (false); - } - - if (! slistSilent) - PrintSlist(); - - if ((Sys_FloatTime() - slistStartTime) < 1.5) - { - SchedulePollProcedure(&slistPollProcedure, 0.1); - return; - } - - if (! slistSilent) - PrintSlistTrailer(); - slistInProgress = false; - slistSilent = false; - slistLocal = true; -} - - -/* -=================== -NET_Connect -=================== -*/ - -int hostCacheCount = 0; -hostcache_t hostcache[HOSTCACHESIZE]; - -qsocket_t *NET_Connect (char *host) -{ - qsocket_t *ret; - int n; - int numdrivers = net_numdrivers; - - SetNetTime(); - - if (host && *host == 0) - host = NULL; - - if (host) - { - if (Q_strcasecmp (host, "local") == 0) - { - numdrivers = 1; - goto JustDoIt; - } - - if (hostCacheCount) - { - for (n = 0; n < hostCacheCount; n++) - if (Q_strcasecmp (host, hostcache[n].name) == 0) - { - host = hostcache[n].cname; - break; - } - if (n < hostCacheCount) - goto JustDoIt; - } - } - - slistSilent = host ? true : false; - NET_Slist_f (); - - while(slistInProgress) - NET_Poll(); - - if (host == NULL) - { - if (hostCacheCount != 1) - return NULL; - host = hostcache[0].cname; - Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host); - } - - if (hostCacheCount) - for (n = 0; n < hostCacheCount; n++) - if (Q_strcasecmp (host, hostcache[n].name) == 0) - { - host = hostcache[n].cname; - break; - } - -JustDoIt: - for (net_driverlevel=0 ; net_driverleveladdress, NET_NAMELEN); - } - return ret; - } - } - - if (recording) - { - vcrConnect.time = host_time; - vcrConnect.op = VCR_OP_CONNECT; - vcrConnect.session = 0; - Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect)); - } - - return NULL; -} - -/* -=================== -NET_Close -=================== -*/ -void NET_Close (qsocket_t *sock) -{ - if (!sock) - return; - - if (sock->disconnected) - return; - - SetNetTime(); - - // call the driver_Close function - sfunc.Close (sock); - - NET_FreeQSocket(sock); -} - - -/* -================= -NET_GetMessage - -If there is a complete message, return it in net_message - -returns 0 if no data is waiting -returns 1 if a message was received -returns -1 if connection is invalid -================= -*/ - -struct -{ - double time; - int op; - long session; - int ret; - int len; -} vcrGetMessage; - -extern void PrintStats(qsocket_t *s); - -int NET_GetMessage (qsocket_t *sock) -{ - int ret; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_GetMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - - ret = sfunc.QGetMessage(sock); - - // see if this connection has timed out - if (ret == 0 && sock->driver) - { - if (net_time - sock->lastMessageTime > net_messagetimeout.value) - { - NET_Close(sock); - return -1; - } - } - - - if (ret > 0) - { - if (sock->driver) - { - sock->lastMessageTime = net_time; - if (ret == 1) - messagesReceived++; - else if (ret == 2) - unreliableMessagesReceived++; - } - - if (recording) - { - vcrGetMessage.time = host_time; - vcrGetMessage.op = VCR_OP_GETMESSAGE; - vcrGetMessage.session = (long)sock; - vcrGetMessage.ret = ret; - vcrGetMessage.len = net_message.cursize; - Sys_FileWrite (vcrFile, &vcrGetMessage, 24); - Sys_FileWrite (vcrFile, net_message.data, net_message.cursize); - } - } - else - { - if (recording) - { - vcrGetMessage.time = host_time; - vcrGetMessage.op = VCR_OP_GETMESSAGE; - vcrGetMessage.session = (long)sock; - vcrGetMessage.ret = ret; - Sys_FileWrite (vcrFile, &vcrGetMessage, 20); - } - } - - return ret; -} - - -/* -================== -NET_SendMessage - -Try to send a complete length+message unit over the reliable stream. -returns 0 if the message cannot be delivered reliably, but the connection - is still considered valid -returns 1 if the message was sent properly -returns -1 if the connection died -================== -*/ -struct -{ - double time; - int op; - long session; - int r; -} vcrSendMessage; - -int NET_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - int r; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_SendMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - r = sfunc.QSendMessage(sock, data); - if (r == 1 && sock->driver) - messagesSent++; - - if (recording) - { - vcrSendMessage.time = host_time; - vcrSendMessage.op = VCR_OP_SENDMESSAGE; - vcrSendMessage.session = (long)sock; - vcrSendMessage.r = r; - Sys_FileWrite (vcrFile, &vcrSendMessage, 20); - } - - return r; -} - - -int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - int r; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_SendMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - r = sfunc.SendUnreliableMessage(sock, data); - if (r == 1 && sock->driver) - unreliableMessagesSent++; - - if (recording) - { - vcrSendMessage.time = host_time; - vcrSendMessage.op = VCR_OP_SENDMESSAGE; - vcrSendMessage.session = (long)sock; - vcrSendMessage.r = r; - Sys_FileWrite (vcrFile, &vcrSendMessage, 20); - } - - return r; -} - - -/* -================== -NET_CanSendMessage - -Returns true or false if the given qsocket can currently accept a -message to be transmitted. -================== -*/ -qboolean NET_CanSendMessage (qsocket_t *sock) -{ - int r; - - if (!sock) - return false; - - if (sock->disconnected) - return false; - - SetNetTime(); - - r = sfunc.CanSendMessage(sock); - - if (recording) - { - vcrSendMessage.time = host_time; - vcrSendMessage.op = VCR_OP_CANSENDMESSAGE; - vcrSendMessage.session = (long)sock; - vcrSendMessage.r = r; - Sys_FileWrite (vcrFile, &vcrSendMessage, 20); - } - - return r; -} - - -int NET_SendToAll(sizebuf_t *data, int blocktime) -{ - double start; - int i; - int count = 0; - qboolean state1 [MAX_SCOREBOARD]; - qboolean state2 [MAX_SCOREBOARD]; - - for (i=0, host_client = svs.clients ; inetconnection) - continue; - if (host_client->active) - { - if (host_client->netconnection->driver == 0) - { - NET_SendMessage(host_client->netconnection, data); - state1[i] = true; - state2[i] = true; - continue; - } - count++; - state1[i] = false; - state2[i] = false; - } - else - { - state1[i] = true; - state2[i] = true; - } - } - - start = Sys_FloatTime(); - while (count) - { - count = 0; - for (i=0, host_client = svs.clients ; inetconnection)) - { - state1[i] = true; - NET_SendMessage(host_client->netconnection, data); - } - else - { - NET_GetMessage (host_client->netconnection); - } - count++; - continue; - } - - if (! state2[i]) - { - if (NET_CanSendMessage (host_client->netconnection)) - { - state2[i] = true; - } - else - { - NET_GetMessage (host_client->netconnection); - } - count++; - continue; - } - } - if ((Sys_FloatTime() - start) > blocktime) - break; - } - return count; -} - - -//============================================================================= - -/* -==================== -NET_Init -==================== -*/ - -void NET_Init (void) -{ - int i; - int controlSocket; - qsocket_t *s; - - if (COM_CheckParm("-playback")) - { - net_numdrivers = 1; - net_drivers[0].Init = VCR_Init; - } - - if (COM_CheckParm("-record")) - recording = true; - - i = COM_CheckParm ("-port"); - if (!i) - i = COM_CheckParm ("-udpport"); - if (!i) - i = COM_CheckParm ("-ipxport"); - - if (i) - { - if (i < com_argc-1) - DEFAULTnet_hostport = Q_atoi (com_argv[i+1]); - else - Sys_Error ("NET_Init: you must specify a number after -port"); - } - net_hostport = DEFAULTnet_hostport; - - if (COM_CheckParm("-listen") || cls.state == ca_dedicated) - listening = true; - net_numsockets = svs.maxclientslimit; - if (cls.state != ca_dedicated) - net_numsockets++; - - SetNetTime(); - - for (i = 0; i < net_numsockets; i++) - { - s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket"); - s->next = net_freeSockets; - net_freeSockets = s; - s->disconnected = true; - } - - // allocate space for network message buffer - SZ_Alloc (&net_message, NET_MAXMESSAGE); - - Cvar_RegisterVariable (&net_messagetimeout); - Cvar_RegisterVariable (&hostname); - Cvar_RegisterVariable (&config_com_port); - Cvar_RegisterVariable (&config_com_irq); - Cvar_RegisterVariable (&config_com_baud); - Cvar_RegisterVariable (&config_com_modem); - Cvar_RegisterVariable (&config_modem_dialtype); - Cvar_RegisterVariable (&config_modem_clear); - Cvar_RegisterVariable (&config_modem_init); - Cvar_RegisterVariable (&config_modem_hangup); -#ifdef IDGODS - Cvar_RegisterVariable (&idgods); -#endif - - Cmd_AddCommand ("slist", NET_Slist_f); - Cmd_AddCommand ("listen", NET_Listen_f); - Cmd_AddCommand ("maxplayers", MaxPlayers_f); - Cmd_AddCommand ("port", NET_Port_f); - - // initialize all the drivers - for (net_driverlevel=0 ; net_driverlevelnext) - NET_Close(sock); - -// -// shutdown the drivers -// - for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (net_drivers[net_driverlevel].initialized == true) - { - net_drivers[net_driverlevel].Shutdown (); - net_drivers[net_driverlevel].initialized = false; - } - } - - if (vcrFile != -1) - { - Con_Printf ("Closing vcrfile.\n"); - Sys_FileClose(vcrFile); - } -} - - -static PollProcedure *pollProcedureList = NULL; - -void NET_Poll(void) -{ - PollProcedure *pp; - qboolean useModem; - - if (!configRestored) - { - if (serialAvailable) - { - if (config_com_modem.value == 1.0) - useModem = true; - else - useModem = false; - SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem); - SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string); - } - configRestored = true; - } - - SetNetTime(); - - for (pp = pollProcedureList; pp; pp = pp->next) - { - if (pp->nextTime > net_time) - break; - pollProcedureList = pp->next; - pp->procedure(pp->arg); - } -} - - -void SchedulePollProcedure(PollProcedure *proc, double timeOffset) -{ - PollProcedure *pp, *prev; - - proc->nextTime = Sys_FloatTime() + timeOffset; - for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next) - { - if (pp->nextTime >= proc->nextTime) - break; - prev = pp; - } - - if (prev == NULL) - { - proc->next = pollProcedureList; - pollProcedureList = proc; - return; - } - - proc->next = pp; - prev->next = proc; -} - - -#ifdef IDGODS -#define IDNET 0xc0f62800 - -qboolean IsID(struct qsockaddr *addr) -{ - if (idgods.value == 0.0) - return false; - - if (addr->sa_family != 2) - return false; - - if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET) - return true; - return false; -} -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_main.c + +#include "quakedef.h" +#include "net_vcr.h" + +qsocket_t *net_activeSockets = NULL; +qsocket_t *net_freeSockets = NULL; +int net_numsockets = 0; + +qboolean serialAvailable = false; +qboolean ipxAvailable = false; +qboolean tcpipAvailable = false; + +int net_hostport; +int DEFAULTnet_hostport = 26000; + +char my_ipx_address[NET_NAMELEN]; +char my_tcpip_address[NET_NAMELEN]; + +void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem); +void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem); +void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); +void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); + +static qboolean listening = false; + +qboolean slistInProgress = false; +qboolean slistSilent = false; +qboolean slistLocal = true; +static double slistStartTime; +static int slistLastShown; + +static void Slist_Send(void); +static void Slist_Poll(void); +PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send}; +PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll}; + + +sizebuf_t net_message; +int net_activeconnections = 0; + +int messagesSent = 0; +int messagesReceived = 0; +int unreliableMessagesSent = 0; +int unreliableMessagesReceived = 0; + +cvar_t net_messagetimeout = {"net_messagetimeout","300"}; +cvar_t hostname = {"hostname", "UNNAMED"}; + +qboolean configRestored = false; +cvar_t config_com_port = {"_config_com_port", "0x3f8", true}; +cvar_t config_com_irq = {"_config_com_irq", "4", true}; +cvar_t config_com_baud = {"_config_com_baud", "57600", true}; +cvar_t config_com_modem = {"_config_com_modem", "1", true}; +cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true}; +cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true}; +cvar_t config_modem_init = {"_config_modem_init", "", true}; +cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true}; + +#ifdef IDGODS +cvar_t idgods = {"idgods", "0"}; +#endif + +int vcrFile = -1; +qboolean recording = false; + +// these two macros are to make the code more readable +#define sfunc net_drivers[sock->driver] +#define dfunc net_drivers[net_driverlevel] + +int net_driverlevel; + + +double net_time; + +double SetNetTime(void) +{ + net_time = Sys_FloatTime(); + return net_time; +} + + +/* +=================== +NET_NewQSocket + +Called by drivers when a new communications endpoint is required +The sequence and buffer fields will be filled in properly +=================== +*/ +qsocket_t *NET_NewQSocket (void) +{ + qsocket_t *sock; + + if (net_freeSockets == NULL) + return NULL; + + if (net_activeconnections >= svs.maxclients) + return NULL; + + // get one from free list + sock = net_freeSockets; + net_freeSockets = sock->next; + + // add it to active list + sock->next = net_activeSockets; + net_activeSockets = sock; + + sock->disconnected = false; + sock->connecttime = net_time; + Q_strcpy (sock->address,"UNSET ADDRESS"); + sock->driver = net_driverlevel; + sock->socket = 0; + sock->driverdata = NULL; + sock->canSend = true; + sock->sendNext = false; + sock->lastMessageTime = net_time; + sock->ackSequence = 0; + sock->sendSequence = 0; + sock->unreliableSendSequence = 0; + sock->sendMessageLength = 0; + sock->receiveSequence = 0; + sock->unreliableReceiveSequence = 0; + sock->receiveMessageLength = 0; + + return sock; +} + + +void NET_FreeQSocket(qsocket_t *sock) +{ + qsocket_t *s; + + // remove it from active list + if (sock == net_activeSockets) + net_activeSockets = net_activeSockets->next; + else + { + for (s = net_activeSockets; s; s = s->next) + if (s->next == sock) + { + s->next = sock->next; + break; + } + if (!s) + Sys_Error ("NET_FreeQSocket: not active\n"); + } + + // add it to free list + sock->next = net_freeSockets; + net_freeSockets = sock; + sock->disconnected = true; +} + + +static void NET_Listen_f (void) +{ + if (Cmd_Argc () != 2) + { + Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0); + return; + } + + listening = Q_atoi(Cmd_Argv(1)) ? true : false; + + for (net_driverlevel=0 ; net_driverlevel svs.maxclientslimit) + { + n = svs.maxclientslimit; + Con_Printf ("\"maxplayers\" set to \"%u\"\n", n); + } + + if ((n == 1) && listening) + Cbuf_AddText ("listen 0\n"); + + if ((n > 1) && (!listening)) + Cbuf_AddText ("listen 1\n"); + + svs.maxclients = n; + if (n == 1) + Cvar_Set ("deathmatch", "0"); + else + Cvar_Set ("deathmatch", "1"); +} + + +static void NET_Port_f (void) +{ + int n; + + if (Cmd_Argc () != 2) + { + Con_Printf ("\"port\" is \"%u\"\n", net_hostport); + return; + } + + n = Q_atoi(Cmd_Argv(1)); + if (n < 1 || n > 65534) + { + Con_Printf ("Bad value, must be between 1 and 65534\n"); + return; + } + + DEFAULTnet_hostport = n; + net_hostport = n; + + if (listening) + { + // force a change to the new port + Cbuf_AddText ("listen 0\n"); + Cbuf_AddText ("listen 1\n"); + } +} + + +static void PrintSlistHeader(void) +{ + Con_Printf("Server Map Users\n"); + Con_Printf("--------------- --------------- -----\n"); + slistLastShown = 0; +} + + +static void PrintSlist(void) +{ + int n; + + for (n = slistLastShown; n < hostCacheCount; n++) + { + if (hostcache[n].maxusers) + Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); + else + Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); + } + slistLastShown = n; +} + + +static void PrintSlistTrailer(void) +{ + if (hostCacheCount) + Con_Printf("== end list ==\n\n"); + else + Con_Printf("No Quake servers found.\n\n"); +} + + +void NET_Slist_f (void) +{ + if (slistInProgress) + return; + + if (! slistSilent) + { + Con_Printf("Looking for Quake servers...\n"); + PrintSlistHeader(); + } + + slistInProgress = true; + slistStartTime = Sys_FloatTime(); + + SchedulePollProcedure(&slistSendProcedure, 0.0); + SchedulePollProcedure(&slistPollProcedure, 0.1); + + hostCacheCount = 0; +} + + +static void Slist_Send(void) +{ + for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (!slistLocal && net_driverlevel == 0) + continue; + if (net_drivers[net_driverlevel].initialized == false) + continue; + dfunc.SearchForHosts (true); + } + + if ((Sys_FloatTime() - slistStartTime) < 0.5) + SchedulePollProcedure(&slistSendProcedure, 0.75); +} + + +static void Slist_Poll(void) +{ + for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (!slistLocal && net_driverlevel == 0) + continue; + if (net_drivers[net_driverlevel].initialized == false) + continue; + dfunc.SearchForHosts (false); + } + + if (! slistSilent) + PrintSlist(); + + if ((Sys_FloatTime() - slistStartTime) < 1.5) + { + SchedulePollProcedure(&slistPollProcedure, 0.1); + return; + } + + if (! slistSilent) + PrintSlistTrailer(); + slistInProgress = false; + slistSilent = false; + slistLocal = true; +} + + +/* +=================== +NET_Connect +=================== +*/ + +int hostCacheCount = 0; +hostcache_t hostcache[HOSTCACHESIZE]; + +qsocket_t *NET_Connect (char *host) +{ + qsocket_t *ret; + int n; + int numdrivers = net_numdrivers; + + SetNetTime(); + + if (host && *host == 0) + host = NULL; + + if (host) + { + if (Q_strcasecmp (host, "local") == 0) + { + numdrivers = 1; + goto JustDoIt; + } + + if (hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (Q_strcasecmp (host, hostcache[n].name) == 0) + { + host = hostcache[n].cname; + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + } + + slistSilent = host ? true : false; + NET_Slist_f (); + + while(slistInProgress) + NET_Poll(); + + if (host == NULL) + { + if (hostCacheCount != 1) + return NULL; + host = hostcache[0].cname; + Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host); + } + + if (hostCacheCount) + for (n = 0; n < hostCacheCount; n++) + if (Q_strcasecmp (host, hostcache[n].name) == 0) + { + host = hostcache[n].cname; + break; + } + +JustDoIt: + for (net_driverlevel=0 ; net_driverleveladdress, NET_NAMELEN); + } + return ret; + } + } + + if (recording) + { + vcrConnect.time = host_time; + vcrConnect.op = VCR_OP_CONNECT; + vcrConnect.session = 0; + Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect)); + } + + return NULL; +} + +/* +=================== +NET_Close +=================== +*/ +void NET_Close (qsocket_t *sock) +{ + if (!sock) + return; + + if (sock->disconnected) + return; + + SetNetTime(); + + // call the driver_Close function + sfunc.Close (sock); + + NET_FreeQSocket(sock); +} + + +/* +================= +NET_GetMessage + +If there is a complete message, return it in net_message + +returns 0 if no data is waiting +returns 1 if a message was received +returns -1 if connection is invalid +================= +*/ + +struct +{ + double time; + int op; + long session; + int ret; + int len; +} vcrGetMessage; + +extern void PrintStats(qsocket_t *s); + +int NET_GetMessage (qsocket_t *sock) +{ + int ret; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_GetMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + + ret = sfunc.QGetMessage(sock); + + // see if this connection has timed out + if (ret == 0 && sock->driver) + { + if (net_time - sock->lastMessageTime > net_messagetimeout.value) + { + NET_Close(sock); + return -1; + } + } + + + if (ret > 0) + { + if (sock->driver) + { + sock->lastMessageTime = net_time; + if (ret == 1) + messagesReceived++; + else if (ret == 2) + unreliableMessagesReceived++; + } + + if (recording) + { + vcrGetMessage.time = host_time; + vcrGetMessage.op = VCR_OP_GETMESSAGE; + vcrGetMessage.session = (long)sock; + vcrGetMessage.ret = ret; + vcrGetMessage.len = net_message.cursize; + Sys_FileWrite (vcrFile, &vcrGetMessage, 24); + Sys_FileWrite (vcrFile, net_message.data, net_message.cursize); + } + } + else + { + if (recording) + { + vcrGetMessage.time = host_time; + vcrGetMessage.op = VCR_OP_GETMESSAGE; + vcrGetMessage.session = (long)sock; + vcrGetMessage.ret = ret; + Sys_FileWrite (vcrFile, &vcrGetMessage, 20); + } + } + + return ret; +} + + +/* +================== +NET_SendMessage + +Try to send a complete length+message unit over the reliable stream. +returns 0 if the message cannot be delivered reliably, but the connection + is still considered valid +returns 1 if the message was sent properly +returns -1 if the connection died +================== +*/ +struct +{ + double time; + int op; + long session; + int r; +} vcrSendMessage; + +int NET_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + int r; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_SendMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + r = sfunc.QSendMessage(sock, data); + if (r == 1 && sock->driver) + messagesSent++; + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_SENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) +{ + int r; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_SendMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + r = sfunc.SendUnreliableMessage(sock, data); + if (r == 1 && sock->driver) + unreliableMessagesSent++; + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_SENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +/* +================== +NET_CanSendMessage + +Returns true or false if the given qsocket can currently accept a +message to be transmitted. +================== +*/ +qboolean NET_CanSendMessage (qsocket_t *sock) +{ + int r; + + if (!sock) + return false; + + if (sock->disconnected) + return false; + + SetNetTime(); + + r = sfunc.CanSendMessage(sock); + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_CANSENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +int NET_SendToAll(sizebuf_t *data, int blocktime) +{ + double start; + int i; + int count = 0; + qboolean state1 [MAX_SCOREBOARD]; + qboolean state2 [MAX_SCOREBOARD]; + + for (i=0, host_client = svs.clients ; inetconnection) + continue; + if (host_client->active) + { + if (host_client->netconnection->driver == 0) + { + NET_SendMessage(host_client->netconnection, data); + state1[i] = true; + state2[i] = true; + continue; + } + count++; + state1[i] = false; + state2[i] = false; + } + else + { + state1[i] = true; + state2[i] = true; + } + } + + start = Sys_FloatTime(); + while (count) + { + count = 0; + for (i=0, host_client = svs.clients ; inetconnection)) + { + state1[i] = true; + NET_SendMessage(host_client->netconnection, data); + } + else + { + NET_GetMessage (host_client->netconnection); + } + count++; + continue; + } + + if (! state2[i]) + { + if (NET_CanSendMessage (host_client->netconnection)) + { + state2[i] = true; + } + else + { + NET_GetMessage (host_client->netconnection); + } + count++; + continue; + } + } + if ((Sys_FloatTime() - start) > blocktime) + break; + } + return count; +} + + +//============================================================================= + +/* +==================== +NET_Init +==================== +*/ + +void NET_Init (void) +{ + int i; + int controlSocket; + qsocket_t *s; + + if (COM_CheckParm("-playback")) + { + net_numdrivers = 1; + net_drivers[0].Init = VCR_Init; + } + + if (COM_CheckParm("-record")) + recording = true; + + i = COM_CheckParm ("-port"); + if (!i) + i = COM_CheckParm ("-udpport"); + if (!i) + i = COM_CheckParm ("-ipxport"); + + if (i) + { + if (i < com_argc-1) + DEFAULTnet_hostport = Q_atoi (com_argv[i+1]); + else + Sys_Error ("NET_Init: you must specify a number after -port"); + } + net_hostport = DEFAULTnet_hostport; + + if (COM_CheckParm("-listen") || cls.state == ca_dedicated) + listening = true; + net_numsockets = svs.maxclientslimit; + if (cls.state != ca_dedicated) + net_numsockets++; + + SetNetTime(); + + for (i = 0; i < net_numsockets; i++) + { + s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket"); + s->next = net_freeSockets; + net_freeSockets = s; + s->disconnected = true; + } + + // allocate space for network message buffer + SZ_Alloc (&net_message, NET_MAXMESSAGE); + + Cvar_RegisterVariable (&net_messagetimeout); + Cvar_RegisterVariable (&hostname); + Cvar_RegisterVariable (&config_com_port); + Cvar_RegisterVariable (&config_com_irq); + Cvar_RegisterVariable (&config_com_baud); + Cvar_RegisterVariable (&config_com_modem); + Cvar_RegisterVariable (&config_modem_dialtype); + Cvar_RegisterVariable (&config_modem_clear); + Cvar_RegisterVariable (&config_modem_init); + Cvar_RegisterVariable (&config_modem_hangup); +#ifdef IDGODS + Cvar_RegisterVariable (&idgods); +#endif + + Cmd_AddCommand ("slist", NET_Slist_f); + Cmd_AddCommand ("listen", NET_Listen_f); + Cmd_AddCommand ("maxplayers", MaxPlayers_f); + Cmd_AddCommand ("port", NET_Port_f); + + // initialize all the drivers + for (net_driverlevel=0 ; net_driverlevelnext) + NET_Close(sock); + +// +// shutdown the drivers +// + for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (net_drivers[net_driverlevel].initialized == true) + { + net_drivers[net_driverlevel].Shutdown (); + net_drivers[net_driverlevel].initialized = false; + } + } + + if (vcrFile != -1) + { + Con_Printf ("Closing vcrfile.\n"); + Sys_FileClose(vcrFile); + } +} + + +static PollProcedure *pollProcedureList = NULL; + +void NET_Poll(void) +{ + PollProcedure *pp; + qboolean useModem; + + if (!configRestored) + { + if (serialAvailable) + { + if (config_com_modem.value == 1.0) + useModem = true; + else + useModem = false; + SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem); + SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string); + } + configRestored = true; + } + + SetNetTime(); + + for (pp = pollProcedureList; pp; pp = pp->next) + { + if (pp->nextTime > net_time) + break; + pollProcedureList = pp->next; + pp->procedure(pp->arg); + } +} + + +void SchedulePollProcedure(PollProcedure *proc, double timeOffset) +{ + PollProcedure *pp, *prev; + + proc->nextTime = Sys_FloatTime() + timeOffset; + for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next) + { + if (pp->nextTime >= proc->nextTime) + break; + prev = pp; + } + + if (prev == NULL) + { + proc->next = pollProcedureList; + pollProcedureList = proc; + return; + } + + proc->next = pp; + prev->next = proc; +} + + +#ifdef IDGODS +#define IDNET 0xc0f62800 + +qboolean IsID(struct qsockaddr *addr) +{ + if (idgods.value == 0.0) + return false; + + if (addr->sa_family != 2) + return false; + + if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET) + return true; + return false; +} +#endif diff --git a/WinQuake/net_mp.c b/WinQuake/net_mp.c index 5d853a5..4f3aeb9 100644 --- a/WinQuake/net_mp.c +++ b/WinQuake/net_mp.c @@ -1,443 +1,443 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_mpath.c - -#include -#include "quakedef.h" -#include "mpdosock.h" - -short flat_selector; - -int WSAGetLastError(void); -void sockets_flush(void); - -extern cvar_t hostname; - -#define MAXHOSTNAMELEN 256 - -static int net_acceptsocket = -1; // socket for fielding new connections -static int net_controlsocket; -static int net_broadcastsocket = 0; -//static qboolean ifbcastinit = false; -static struct qsockaddr broadcastaddr; - -static unsigned long myAddr; - -#include "net_mp.h" - - -//============================================================================= - -int MPATH_Init (void) -{ - int i; - struct hostent *local = NULL; - char buff[MAXHOSTNAMELEN]; - struct qsockaddr addr; - char *p; - - if (COM_CheckParm ("-mpath") == 0) - return -1; - - flat_selector = __dpmi_allocate_ldt_descriptors(1); - if (flat_selector == -1) { - Con_Printf("MPATH_Init: Can't get flat selector\n"); - return -1; - } - if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) { - Con_Printf("MPATH_Init: Can't seg flat base!\n"); - return -1; - } - if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) { - Con_Printf("MPATH_Init: Can't set segment limit\n"); - return -1; - } - // determine my name & address - if (gethostname(buff, MAXHOSTNAMELEN) == 0) - local = gethostbyname(buff); - if (local) - { - myAddr = *(int *)local->h_addr_list[0]; - - // if the quake hostname isn't set, set it to the machine name - if (Q_strcmp(hostname.string, "UNNAMED") == 0) - { - // see if it's a text IP address (well, close enough) - for (p = buff; *p; p++) - if ((*p < '0' || *p > '9') && *p != '.') - break; - - // if it is a real name, strip off the domain; we only want the host - if (*p) - { - for (i = 0; i < 15; i++) - if (buff[i] == '.') - break; - buff[i] = 0; - } - Cvar_Set ("hostname", buff); - } - } - - if ((net_controlsocket = MPATH_OpenSocket (0)) == -1) - Sys_Error("MPATH_Init: Unable to open control socket\n"); - - ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; - ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; - ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport); - - MPATH_GetSocketAddr (net_controlsocket, &addr); - Q_strcpy(my_tcpip_address, MPATH_AddrToString (&addr)); - p = Q_strrchr (my_tcpip_address, ':'); - if (p) - *p = 0; - - Con_Printf("MPath Initialized\n"); - tcpipAvailable = true; - - return net_controlsocket; -} - -//============================================================================= - -void MPATH_Shutdown (void) -{ - MPATH_Listen (false); - MPATH_CloseSocket (net_controlsocket); -} - -//============================================================================= - -void MPATH_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1) - Sys_Error ("MPATH_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - MPATH_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - -//============================================================================= - -int MPATH_OpenSocket (int port) -{ - int newsocket; - struct sockaddr_in address; - u_long _true = 1; - - if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - return -1; - - if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) - goto ErrorReturn; - - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(port); - if( bind (newsocket, (void *)&address, sizeof(address)) == -1) - goto ErrorReturn; - - return newsocket; - -ErrorReturn: - closesocket (newsocket); - return -1; -} - -//============================================================================= - -int MPATH_CloseSocket (int socket) -{ - if (socket == net_broadcastsocket) - net_broadcastsocket = 0; - return closesocket (socket); -} - - -//============================================================================= -/* -============ -PartialIPAddress - -this lets you type only as much of the net address as required, using -the local network components to fill in the rest -============ -*/ -static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) -{ - char buff[256]; - char *b; - int addr; - int num; - int mask; - int run; - int port; - - buff[0] = '.'; - b = buff; - strcpy(buff+1, in); - if (buff[1] == '.') - b++; - - addr = 0; - mask=-1; - while (*b == '.') - { - b++; - num = 0; - run = 0; - while (!( *b < '0' || *b > '9')) - { - num = num*10 + *b++ - '0'; - if (++run > 3) - return -1; - } - if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) - return -1; - if (num < 0 || num > 255) - return -1; - mask<<=8; - addr = (addr<<8) + num; - } - - if (*b++ == ':') - port = Q_atoi(b); - else - port = net_hostport; - - hostaddr->sa_family = AF_INET; - ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); - ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); - - return 0; -} -//============================================================================= - -int MPATH_Connect (int socket, struct qsockaddr *addr) -{ - return 0; -} - -//============================================================================= - -int MPATH_CheckNewConnections (void) -{ - char buf[4]; - - if (net_acceptsocket == -1) - return -1; - - if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0) - return net_acceptsocket; - return -1; -} - -//============================================================================= - -int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr) -{ - int addrlen = sizeof (struct qsockaddr); - int ret; - - ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); - if (ret == -1) - { - int errno = WSAGetLastError(); - - if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) - return 0; - - } - return ret; -} - -//============================================================================= - -int MPATH_MakeSocketBroadcastCapable (int socket) -{ - int i = 1; - - // make this socket broadcast capable - if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) - return -1; - net_broadcastsocket = socket; - - return 0; -} - -//============================================================================= - -int MPATH_Broadcast (int socket, byte *buf, int len) -{ - int ret; - - if (socket != net_broadcastsocket) - { - if (net_broadcastsocket != 0) - Sys_Error("Attempted to use multiple broadcasts sockets\n"); - ret = MPATH_MakeSocketBroadcastCapable (socket); - if (ret == -1) - { - Con_Printf("Unable to make socket broadcast capable\n"); - return ret; - } - } - - return MPATH_Write (socket, buf, len, &broadcastaddr); -} - -//============================================================================= - -int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr) -{ - int ret; - - ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); - if (ret == -1) - if (WSAGetLastError() == WSAEWOULDBLOCK) - return 0; - - sockets_flush(); - - return ret; -} - -//============================================================================= - -char *MPATH_AddrToString (struct qsockaddr *addr) -{ - static char buffer[22]; - int haddr; - - haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); - sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); - return buffer; -} - -//============================================================================= - -int MPATH_StringToAddr (char *string, struct qsockaddr *addr) -{ - int ha1, ha2, ha3, ha4, hp; - int ipaddr; - - sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); - ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); - ((struct sockaddr_in *)addr)->sin_port = htons(hp); - return 0; -} - -//============================================================================= - -int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr) -{ - int addrlen = sizeof(struct qsockaddr); - unsigned int a; - - Q_memset(addr, 0, sizeof(struct qsockaddr)); - getsockname(socket, (struct sockaddr *)addr, &addrlen); - a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; - if (a == 0 || a == inet_addr("127.0.0.1")) - ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; - - return 0; -} - -//============================================================================= - -int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name) -{ - struct hostent *hostentry; - - hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); - if (hostentry) - { - Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); - return 0; - } - - Q_strcpy (name, MPATH_AddrToString (addr)); - return 0; -} - -//============================================================================= - -int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr) -{ - struct hostent *hostentry; - - if (name[0] >= '0' && name[0] <= '9') - return PartialIPAddress (name, addr); - - hostentry = gethostbyname (name); - if (!hostentry) - return -1; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); - ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; - - return 0; -} - -//============================================================================= - -int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) - return 1; - - return 0; -} - -//============================================================================= - -int MPATH_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_in *)addr)->sin_port); -} - - -int MPATH_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_in *)addr)->sin_port = htons(port); - return 0; -} - -//============================================================================= +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_mpath.c + +#include +#include "quakedef.h" +#include "mpdosock.h" + +short flat_selector; + +int WSAGetLastError(void); +void sockets_flush(void); + +extern cvar_t hostname; + +#define MAXHOSTNAMELEN 256 + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket; +static int net_broadcastsocket = 0; +//static qboolean ifbcastinit = false; +static struct qsockaddr broadcastaddr; + +static unsigned long myAddr; + +#include "net_mp.h" + + +//============================================================================= + +int MPATH_Init (void) +{ + int i; + struct hostent *local = NULL; + char buff[MAXHOSTNAMELEN]; + struct qsockaddr addr; + char *p; + + if (COM_CheckParm ("-mpath") == 0) + return -1; + + flat_selector = __dpmi_allocate_ldt_descriptors(1); + if (flat_selector == -1) { + Con_Printf("MPATH_Init: Can't get flat selector\n"); + return -1; + } + if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) { + Con_Printf("MPATH_Init: Can't seg flat base!\n"); + return -1; + } + if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) { + Con_Printf("MPATH_Init: Can't set segment limit\n"); + return -1; + } + // determine my name & address + if (gethostname(buff, MAXHOSTNAMELEN) == 0) + local = gethostbyname(buff); + if (local) + { + myAddr = *(int *)local->h_addr_list[0]; + + // if the quake hostname isn't set, set it to the machine name + if (Q_strcmp(hostname.string, "UNNAMED") == 0) + { + // see if it's a text IP address (well, close enough) + for (p = buff; *p; p++) + if ((*p < '0' || *p > '9') && *p != '.') + break; + + // if it is a real name, strip off the domain; we only want the host + if (*p) + { + for (i = 0; i < 15; i++) + if (buff[i] == '.') + break; + buff[i] = 0; + } + Cvar_Set ("hostname", buff); + } + } + + if ((net_controlsocket = MPATH_OpenSocket (0)) == -1) + Sys_Error("MPATH_Init: Unable to open control socket\n"); + + ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; + ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport); + + MPATH_GetSocketAddr (net_controlsocket, &addr); + Q_strcpy(my_tcpip_address, MPATH_AddrToString (&addr)); + p = Q_strrchr (my_tcpip_address, ':'); + if (p) + *p = 0; + + Con_Printf("MPath Initialized\n"); + tcpipAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void MPATH_Shutdown (void) +{ + MPATH_Listen (false); + MPATH_CloseSocket (net_controlsocket); +} + +//============================================================================= + +void MPATH_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1) + Sys_Error ("MPATH_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + MPATH_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int MPATH_OpenSocket (int port) +{ + int newsocket; + struct sockaddr_in address; + u_long _true = 1; + + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + return -1; + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + goto ErrorReturn; + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + goto ErrorReturn; + + return newsocket; + +ErrorReturn: + closesocket (newsocket); + return -1; +} + +//============================================================================= + +int MPATH_CloseSocket (int socket) +{ + if (socket == net_broadcastsocket) + net_broadcastsocket = 0; + return closesocket (socket); +} + + +//============================================================================= +/* +============ +PartialIPAddress + +this lets you type only as much of the net address as required, using +the local network components to fill in the rest +============ +*/ +static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) +{ + char buff[256]; + char *b; + int addr; + int num; + int mask; + int run; + int port; + + buff[0] = '.'; + b = buff; + strcpy(buff+1, in); + if (buff[1] == '.') + b++; + + addr = 0; + mask=-1; + while (*b == '.') + { + b++; + num = 0; + run = 0; + while (!( *b < '0' || *b > '9')) + { + num = num*10 + *b++ - '0'; + if (++run > 3) + return -1; + } + if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) + return -1; + if (num < 0 || num > 255) + return -1; + mask<<=8; + addr = (addr<<8) + num; + } + + if (*b++ == ':') + port = Q_atoi(b); + else + port = net_hostport; + + hostaddr->sa_family = AF_INET; + ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); + ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); + + return 0; +} +//============================================================================= + +int MPATH_Connect (int socket, struct qsockaddr *addr) +{ + return 0; +} + +//============================================================================= + +int MPATH_CheckNewConnections (void) +{ + char buf[4]; + + if (net_acceptsocket == -1) + return -1; + + if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0) + return net_acceptsocket; + return -1; +} + +//============================================================================= + +int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int addrlen = sizeof (struct qsockaddr); + int ret; + + ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); + if (ret == -1) + { + int errno = WSAGetLastError(); + + if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) + return 0; + + } + return ret; +} + +//============================================================================= + +int MPATH_MakeSocketBroadcastCapable (int socket) +{ + int i = 1; + + // make this socket broadcast capable + if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) + return -1; + net_broadcastsocket = socket; + + return 0; +} + +//============================================================================= + +int MPATH_Broadcast (int socket, byte *buf, int len) +{ + int ret; + + if (socket != net_broadcastsocket) + { + if (net_broadcastsocket != 0) + Sys_Error("Attempted to use multiple broadcasts sockets\n"); + ret = MPATH_MakeSocketBroadcastCapable (socket); + if (ret == -1) + { + Con_Printf("Unable to make socket broadcast capable\n"); + return ret; + } + } + + return MPATH_Write (socket, buf, len, &broadcastaddr); +} + +//============================================================================= + +int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int ret; + + ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); + if (ret == -1) + if (WSAGetLastError() == WSAEWOULDBLOCK) + return 0; + + sockets_flush(); + + return ret; +} + +//============================================================================= + +char *MPATH_AddrToString (struct qsockaddr *addr) +{ + static char buffer[22]; + int haddr; + + haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); + sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); + return buffer; +} + +//============================================================================= + +int MPATH_StringToAddr (char *string, struct qsockaddr *addr) +{ + int ha1, ha2, ha3, ha4, hp; + int ipaddr; + + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); + ((struct sockaddr_in *)addr)->sin_port = htons(hp); + return 0; +} + +//============================================================================= + +int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr) +{ + int addrlen = sizeof(struct qsockaddr); + unsigned int a; + + Q_memset(addr, 0, sizeof(struct qsockaddr)); + getsockname(socket, (struct sockaddr *)addr, &addrlen); + a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + if (a == 0 || a == inet_addr("127.0.0.1")) + ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; + + return 0; +} + +//============================================================================= + +int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + struct hostent *hostentry; + + hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); + if (hostentry) + { + Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); + return 0; + } + + Q_strcpy (name, MPATH_AddrToString (addr)); + return 0; +} + +//============================================================================= + +int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr) +{ + struct hostent *hostentry; + + if (name[0] >= '0' && name[0] <= '9') + return PartialIPAddress (name, addr); + + hostentry = gethostbyname (name); + if (!hostentry) + return -1; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); + ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; + + return 0; +} + +//============================================================================= + +int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) + return 1; + + return 0; +} + +//============================================================================= + +int MPATH_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_in *)addr)->sin_port); +} + + +int MPATH_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_in *)addr)->sin_port = htons(port); + return 0; +} + +//============================================================================= diff --git a/WinQuake/net_mp.h b/WinQuake/net_mp.h index 13e1675..8a8e350 100644 --- a/WinQuake/net_mp.h +++ b/WinQuake/net_mp.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_mpath.h - -int MPATH_Init (void); -void MPATH_Shutdown (void); -void MPATH_Listen (qboolean state); -int MPATH_OpenSocket (int port); -int MPATH_CloseSocket (int socket); -int MPATH_Connect (int socket, struct qsockaddr *addr); -int MPATH_CheckNewConnections (void); -int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int MPATH_Broadcast (int socket, byte *buf, int len); -char *MPATH_AddrToString (struct qsockaddr *addr); -int MPATH_StringToAddr (char *string, struct qsockaddr *addr); -int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr); -int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name); -int MPATH_GetAddrFromName (char *name, struct qsockaddr *addr); -int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int MPATH_GetSocketPort (struct qsockaddr *addr); -int MPATH_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_mpath.h + +int MPATH_Init (void); +void MPATH_Shutdown (void); +void MPATH_Listen (qboolean state); +int MPATH_OpenSocket (int port); +int MPATH_CloseSocket (int socket); +int MPATH_Connect (int socket, struct qsockaddr *addr); +int MPATH_CheckNewConnections (void); +int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int MPATH_Broadcast (int socket, byte *buf, int len); +char *MPATH_AddrToString (struct qsockaddr *addr); +int MPATH_StringToAddr (char *string, struct qsockaddr *addr); +int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr); +int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name); +int MPATH_GetAddrFromName (char *name, struct qsockaddr *addr); +int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int MPATH_GetSocketPort (struct qsockaddr *addr); +int MPATH_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/net_none.c b/WinQuake/net_none.c index c00c975..b6e6968 100644 --- a/WinQuake/net_none.c +++ b/WinQuake/net_none.c @@ -1,46 +1,46 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -#include "net_loop.h" - -net_driver_t net_drivers[MAX_NET_DRIVERS] = -{ - { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown - } -}; -int net_numdrivers = 1; - -net_landriver_t net_landrivers[MAX_NET_DRIVERS]; -int net_numlandrivers = 0; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +#include "net_loop.h" + +net_driver_t net_drivers[MAX_NET_DRIVERS] = +{ + { + "Loopback", + false, + Loop_Init, + Loop_Listen, + Loop_SearchForHosts, + Loop_Connect, + Loop_CheckNewConnections, + Loop_GetMessage, + Loop_SendMessage, + Loop_SendUnreliableMessage, + Loop_CanSendMessage, + Loop_CanSendUnreliableMessage, + Loop_Close, + Loop_Shutdown + } +}; +int net_numdrivers = 1; + +net_landriver_t net_landrivers[MAX_NET_DRIVERS]; +int net_numlandrivers = 0; diff --git a/WinQuake/net_ser.c b/WinQuake/net_ser.c index f582f54..d80b3b1 100644 --- a/WinQuake/net_ser.c +++ b/WinQuake/net_ser.c @@ -1,951 +1,951 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_ser.c - -#include "quakedef.h" -#include "net_ser.h" -#include "dosisms.h" -#include "crc.h" - -#include "net_comx.c" - -// serial protocol - -#define SERIAL_PROTOCOL_VERSION 3 - -// The serial protocol is message oriented. The high level message format is -// a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All -// multi-byte fields are sent in network byte order. There are currently 4 -// MTYPEs defined. Their formats are as follows: -// -// MTYPE_RELIABLE sequence data_length data checksum eom -// MTYPE_UNRELIABLE sequence data_length data checksum eom -// MTYPE_ACK sequence checksum eom -// MTYPE_CONTROL data_length data checksum eom -// -// sequence is an 8-bit unsigned value starting from 0 -// data_length is a 16-bit unsigned value; it is the length of the data only -// the checksum is a 16-bit value. the CRC formula used is defined in crc.h. -// the checksum covers the entire messages, excluding itself -// eom is a special 2 byte sequence used to mark the End Of Message. This is -// needed for error recovery. -// -// A lot of behavior is based on knowledge of the upper level Quake network -// layer. For example, only one reliable message can be outstanding (pending -// reception of an MTYPE_ACK) at a time. -// -// The low level routines used to communicate with the modem are not part of -// this protocol. -// -// The CONTROL messages are only used for session establishment. They are -// not reliable or sequenced. - -#define MTYPE_RELIABLE 0x01 -#define MTYPE_UNRELIABLE 0x02 -#define MTYPE_CONTROL 0x03 -#define MTYPE_ACK 0x04 -#define MTYPE_CLIENT 0x80 - -#define ESCAPE_COMMAND 0xe0 -#define ESCAPE_EOM 0x19 - -static qboolean listening = false; - - -typedef struct SerialLine_s -{ - struct SerialLine_s *next; - qsocket_t *sock; - int lengthStated; - int lengthFound; - int tty; - qboolean connected; - qboolean connecting; - qboolean client; - double connect_time; - unsigned short crcStated; - unsigned short crcValue; - byte currState; - byte prevState; - byte mtype; - byte sequence; -} SerialLine; - -#define STATE_READY 0 -#define STATE_SEQUENCE 1 -#define STATE_LENGTH1 2 -#define STATE_LENGTH2 3 -#define STATE_DATA 4 -#define STATE_CRC1 5 -#define STATE_CRC2 6 -#define STATE_EOM 7 -#define STATE_ESCAPE 8 -#define STATE_ABORT 9 - -SerialLine serialLine[NUM_COM_PORTS]; - -int myDriverLevel; - -static void Serial_SendACK (SerialLine *p, byte sequence); - - -static void ResetSerialLineProtocol (SerialLine *p) -{ - p->connected = false; - p->connecting = false; - p->currState = STATE_READY; - p->prevState = STATE_READY; - p->lengthFound = 0; -} - - -static int ProcessInQueue(SerialLine *p) -{ - int b; - - while (1) - { - b = TTY_ReadByte(p->tty); - if (b == ERR_TTY_NODATA) - break; - - if (b == ERR_TTY_LINE_STATUS) - { - p->currState = STATE_ABORT; - continue; - } - if (b == ERR_TTY_MODEM_STATUS) - { - p->currState = STATE_ABORT; - return -1; - } - - if (b == ESCAPE_COMMAND) - if (p->currState != STATE_ESCAPE) - { - p->prevState = p->currState; - p->currState = STATE_ESCAPE; - continue; - } - - if (p->currState == STATE_ESCAPE) - { - if (b == ESCAPE_EOM) - { - if (p->prevState == STATE_ABORT) - { - p->currState = STATE_READY; - p->lengthFound = 0; - continue; - } - - if (p->prevState != STATE_EOM) - { - p->currState = STATE_READY; - p->lengthFound = 0; - Con_DPrintf("Serial: premature EOM\n"); - continue; - } - - switch (p->mtype) - { - case MTYPE_RELIABLE: - Con_DPrintf("Serial: sending ack %u\n", p->sequence); - Serial_SendACK (p, p->sequence); - if (p->sequence == p->sock->receiveSequence) - { - p->sock->receiveSequence = (p->sequence + 1) & 0xff; - p->sock->receiveMessageLength += p->lengthFound; - } - else - Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence); - break; - - case MTYPE_UNRELIABLE: - p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff; - p->sock->receiveMessageLength += p->lengthFound; - break; - - case MTYPE_ACK: - Con_DPrintf("Serial: got ack %u\n", p->sequence); - if (p->sequence == p->sock->sendSequence) - { - p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff; - p->sock->canSend = true; - } - else - Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence); - break; - - case MTYPE_CONTROL: - p->sock->receiveMessageLength += p->lengthFound; - break; - } - - p->currState = STATE_READY; - p->lengthFound = 0; - continue; - } - - - if (b != ESCAPE_COMMAND) - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: Bad escape sequence\n"); - continue; - } - - // b == ESCAPE_COMMAND - p->currState = p->prevState; - } - - p->prevState = p->currState; - -//DEBUG - if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE) - { - Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound); - p->currState = STATE_ABORT; - } - if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE) - { - Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound); - p->currState = STATE_ABORT; - } -//end DEBUG - - switch (p->currState) - { - case STATE_READY: - CRC_Init(&p->crcValue); - CRC_ProcessByte(&p->crcValue, b); - if (p->client) - { - if ((b & MTYPE_CLIENT) != 0) - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: client got own message\n"); - break; - } - } - else - { - if ((b & MTYPE_CLIENT) == 0) - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: server got own message\n"); - break; - } - b &= 0x7f; - } - p->mtype = b; - if (b != MTYPE_CONTROL) - p->currState = STATE_SEQUENCE; - else - p->currState = STATE_LENGTH1; - if (p->mtype < MTYPE_ACK) - { - p->sock->receiveMessage[p->sock->receiveMessageLength] = b; - p->lengthFound++; - } - break; - - case STATE_SEQUENCE: - p->sequence = b; - CRC_ProcessByte(&p->crcValue, b); - if (p->mtype != MTYPE_ACK) - p->currState = STATE_LENGTH1; - else - p->currState = STATE_CRC1; - break; - - case STATE_LENGTH1: - p->lengthStated = b * 256; - CRC_ProcessByte(&p->crcValue, b); - p->currState = STATE_LENGTH2; - break; - - case STATE_LENGTH2: - p->lengthStated += b; - CRC_ProcessByte(&p->crcValue, b); - if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN) - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated); - } - else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM) - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated); - } - else - { - p->currState = STATE_DATA; - if (p->mtype < MTYPE_ACK) - { - *(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated; - p->lengthFound += 2; - } - } - break; - - case STATE_DATA: - p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b; - p->lengthFound++; - CRC_ProcessByte(&p->crcValue, b); - if (p->lengthFound == p->lengthStated + 3) - p->currState = STATE_CRC1; - break; - - case STATE_CRC1: - p->crcStated = b * 256; - p->currState = STATE_CRC2; - break; - - case STATE_CRC2: - p->crcStated += b; - if (p->crcStated == CRC_Value(p->crcValue)) - { - p->currState = STATE_EOM; - } - else - { - p->currState = STATE_ABORT; - Con_DPrintf("Serial: Bad crc\n"); - } - break; - - case STATE_EOM: - p->currState = STATE_ABORT; - Con_DPrintf("Serial: Bad message format\n"); - break; - - case STATE_ABORT: - break; - } - } - return 0; -} - - -int Serial_Init (void) -{ - int n; - -// LATER do Win32 serial support -#ifdef _WIN32 - return -1; -#endif - - if (COM_CheckParm("-nolan")) - return -1; - if (COM_CheckParm ("-noserial")) - return -1; - - myDriverLevel = net_driverlevel; - - if (TTY_Init()) - return -1; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - serialLine[n].tty = TTY_Open(n); - ResetSerialLineProtocol (&serialLine[n]); - } - - Con_Printf("Serial driver initialized\n"); - serialAvailable = true; - - return 0; -} - - -void Serial_Shutdown (void) -{ - int n; - - for (n = 0; n < NUM_COM_PORTS; n++) - { - if (serialLine[n].connected) - Serial_Close(serialLine[n].sock); - } - - TTY_Shutdown(); -} - - -void Serial_Listen (qboolean state) -{ - listening = state; -} - - -qboolean Serial_CanSendMessage (qsocket_t *sock) -{ - return sock->canSend; -} - - -qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock) -{ - return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty); -} - - -int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message) -{ - SerialLine *p; - int n; - unsigned short crc; - byte b; - - p = (SerialLine *)sock->driverdata; - CRC_Init (&crc); - - // message type - b = MTYPE_RELIABLE; - if (p->client) - b |= MTYPE_CLIENT; - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // sequence - b = p->sock->sendSequence; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data length - b = message->cursize >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - b = message->cursize & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data - for (n = 0; n < message->cursize; n++) - { - b = message->data[n]; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - } - - // checksum - b = CRC_Value (crc) >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - b = CRC_Value (crc) & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - - // end of message - TTY_WriteByte(p->tty, ESCAPE_COMMAND); - TTY_WriteByte(p->tty, ESCAPE_EOM); - - TTY_Flush(p->tty); - - // mark sock as busy and save the message for possible retransmit - sock->canSend = false; - Q_memcpy(sock->sendMessage, message->data, message->cursize); - sock->sendMessageLength = message->cursize; - sock->lastSendTime = net_time; - - return 1; -} - - -static void ReSendMessage (qsocket_t *sock) -{ - sizebuf_t temp; - - Con_DPrintf("Serial: re-sending reliable\n"); - temp.data = sock->sendMessage; - temp.maxsize = sock->sendMessageLength; - temp.cursize = sock->sendMessageLength; - Serial_SendMessage (sock, &temp); -} - - -int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message) -{ - SerialLine *p; - int n; - unsigned short crc; - byte b; - - p = (SerialLine *)sock->driverdata; - - if (!TTY_OutputQueueIsEmpty(p->tty)) - { - TTY_Flush(p->tty); - return 1; - } - - CRC_Init (&crc); - - // message type - b = MTYPE_UNRELIABLE; - if (p->client) - b |= MTYPE_CLIENT; - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // sequence - b = p->sock->unreliableSendSequence; - p->sock->unreliableSendSequence = (b + 1) & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data length - b = message->cursize >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - b = message->cursize & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data - for (n = 0; n < message->cursize; n++) - { - b = message->data[n]; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - } - - // checksum - b = CRC_Value (crc) >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - b = CRC_Value (crc) & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - - // end of message - TTY_WriteByte(p->tty, ESCAPE_COMMAND); - TTY_WriteByte(p->tty, ESCAPE_EOM); - - TTY_Flush(p->tty); - - return 1; -} - - -static void Serial_SendACK (SerialLine *p, byte sequence) -{ - unsigned short crc; - byte b; - - CRC_Init (&crc); - - // message type - b = MTYPE_ACK; - if (p->client) - b |= MTYPE_CLIENT; - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // sequence - b = sequence; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // checksum - b = CRC_Value (crc) >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - b = CRC_Value (crc) & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - - // end of message - TTY_WriteByte(p->tty, ESCAPE_COMMAND); - TTY_WriteByte(p->tty, ESCAPE_EOM); - - TTY_Flush(p->tty); -} - - -static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message) -{ - unsigned short crc; - int n; - byte b; - - CRC_Init (&crc); - - // message type - b = MTYPE_CONTROL; - if (p->client) - b |= MTYPE_CLIENT; - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data length - b = message->cursize >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - b = message->cursize & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - - // data - for (n = 0; n < message->cursize; n++) - { - b = message->data[n]; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - CRC_ProcessByte (&crc, b); - } - - // checksum - b = CRC_Value (crc) >> 8; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - b = CRC_Value (crc) & 0xff; - TTY_WriteByte(p->tty, b); - if (b == ESCAPE_COMMAND) - TTY_WriteByte(p->tty, b); - - // end of message - TTY_WriteByte(p->tty, ESCAPE_COMMAND); - TTY_WriteByte(p->tty, ESCAPE_EOM); - - TTY_Flush(p->tty); -} - - -static int _Serial_GetMessage (SerialLine *p) -{ - byte ret; - short length; - - if (ProcessInQueue(p)) - return -1; - - if (p->sock->receiveMessageLength == 0) - return 0; - - ret = p->sock->receiveMessage[0]; - length = *(short *)&p->sock->receiveMessage[1]; - if (ret == MTYPE_CONTROL) - ret = 1; - - SZ_Clear (&net_message); - SZ_Write (&net_message, &p->sock->receiveMessage[3], length); - - length += 3; - p->sock->receiveMessageLength -= length; - - if (p->sock->receiveMessageLength + p->lengthFound) - Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound); - - return ret; -} - -int Serial_GetMessage (qsocket_t *sock) -{ - SerialLine *p; - int ret; - - p = (SerialLine *)sock->driverdata; - - ret = _Serial_GetMessage (p); - - if (ret == 1) - messagesReceived++; - - if (!sock->canSend) - if ((net_time - sock->lastSendTime) > 1.0) - { - ReSendMessage (sock); - sock->lastSendTime = net_time; - } - - return ret; -} - - -void Serial_Close (qsocket_t *sock) -{ - SerialLine *p = (SerialLine *)sock->driverdata; - TTY_Close(p->tty); - ResetSerialLineProtocol (p); -} - - -char *com_types[] = {"direct", "modem"}; -unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600}; - -void Serial_SearchForHosts (qboolean xmit) -{ - int n; - SerialLine *p; - - if (sv.active) - return; - - if (hostCacheCount == HOSTCACHESIZE) - return; - - // see if we've already answered - for (n = 0; n < hostCacheCount; n++) - if (Q_strcmp (hostcache[n].cname, "#") == 0) - return; - - for (n = 0; n < NUM_COM_PORTS; n++) - if (TTY_IsEnabled(n)) - break; - if (n == NUM_COM_PORTS) - return; - p = &serialLine[n]; - - if (TTY_IsModem(p->tty)) - return; - - sprintf(hostcache[hostCacheCount].name, "COM%u", n+1); - Q_strcpy(hostcache[hostCacheCount].map, ""); - hostcache[hostCacheCount].users = 0; - hostcache[hostCacheCount].maxusers = 0; - hostcache[hostCacheCount].driver = net_driverlevel; - Q_strcpy(hostcache[hostCacheCount].cname, "#"); - hostCacheCount++; - - return; -} - - -static qsocket_t *_Serial_Connect (char *host, SerialLine *p) -{ - int ret; - double start_time; - double last_time; - - p->client = true; - if (TTY_Connect(p->tty, host)) - return NULL; - - p->sock = NET_NewQSocket (); - p->sock->driver = myDriverLevel; - if (p->sock == NULL) - { - Con_Printf("No sockets available\n"); - return NULL; - } - p->sock->driverdata = p; - - // send the connection request - start_time = SetNetTime(); - last_time = 0.0; - - SZ_Clear(&net_message); - MSG_WriteByte(&net_message, CCREQ_CONNECT); - MSG_WriteString(&net_message, "QUAKE"); - do - { - SetNetTime(); - if ((net_time - last_time) >= 1.0) - { - Serial_SendControlMessage (p, &net_message); - last_time = net_time; - Con_Printf("trying...\n"); SCR_UpdateScreen (); - } - ret = _Serial_GetMessage (p); - } - while (ret == 0 && (net_time - start_time) < 5.0); - - if (ret == 0) - { - Con_Printf("Unable to connect, no response\n"); - goto ErrorReturn; - } - - if (ret == -1) - { - Con_Printf("Connection request error\n"); - goto ErrorReturn; - } - - MSG_BeginReading (); - ret = MSG_ReadByte(); - if (ret == CCREP_REJECT) - { - Con_Printf(MSG_ReadString()); - goto ErrorReturn; - } - if (ret != CCREP_ACCEPT) - { - Con_Printf("Unknown connection response\n"); - goto ErrorReturn; - } - - p->connected = true; - p->sock->lastMessageTime = net_time; - - Con_Printf ("Connection accepted\n"); - - return p->sock; - -ErrorReturn: - TTY_Disconnect(p->tty); - return NULL; -} - -qsocket_t *Serial_Connect (char *host) -{ - int n; - qsocket_t *ret = NULL; - - // see if this looks like a phone number - if (*host == '#') - host++; - for (n = 0; n < Q_strlen(host); n++) - if (host[n] == '.' || host[n] == ':') - return NULL; - - for (n = 0; n < NUM_COM_PORTS; n++) - if (TTY_IsEnabled(n) && !serialLine[n].connected) - if ((ret = _Serial_Connect (host, &serialLine[n]))) - break; - return ret; -} - - -static qsocket_t *_Serial_CheckNewConnections (SerialLine *p) -{ - int command; - - p->client = false; - if (!TTY_CheckForConnection(p->tty)) - return NULL; - - if (TTY_IsModem(p->tty)) - { - if (!p->connecting) - { - p->connecting = true; - p->connect_time = net_time; - } - else if ((net_time - p->connect_time) > 15.0) - { - p->connecting = false; - TTY_Disconnect(p->tty); - return NULL; - } - } - - p->sock = NET_NewQSocket (); - p->sock->driver = myDriverLevel; - if (p->sock == NULL) - { - Con_Printf("No sockets available\n"); - return NULL; - } - p->sock->driverdata = p; - - SZ_Clear(&net_message); - if (_Serial_GetMessage(p) != 1) - { - NET_FreeQSocket(p->sock); - return NULL; - } - - MSG_BeginReading (); - command = MSG_ReadByte(); - - if (command == CCREQ_SERVER_INFO) - { - if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION) - return NULL; - - SZ_Clear(&net_message); - MSG_WriteByte(&net_message, CCREP_SERVER_INFO); - MSG_WriteString(&net_message, hostname.string); - MSG_WriteString(&net_message, sv.name); - MSG_WriteByte(&net_message, net_activeconnections); - MSG_WriteByte(&net_message, svs.maxclients); - Serial_SendControlMessage (p, &net_message); - SZ_Clear(&net_message); - return NULL; - } - - if (command != CCREQ_CONNECT) - return NULL; - - if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - // send him back the info about the server connection he has been allocated - SZ_Clear(&net_message); - MSG_WriteByte(&net_message, CCREP_ACCEPT); - Serial_SendControlMessage (p, &net_message); - SZ_Clear(&net_message); - - p->connected = true; - p->connecting = false; - p->sock->lastMessageTime = net_time; - sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1)); - - return p->sock; -} - -qsocket_t *Serial_CheckNewConnections (void) -{ - int n; - qsocket_t *ret = NULL; - - for (n = 0; n < NUM_COM_PORTS; n++) - if (TTY_IsEnabled(n) && !serialLine[n].connected) - if ((ret = _Serial_CheckNewConnections (&serialLine[n]))) - break; - return ret; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_ser.c + +#include "quakedef.h" +#include "net_ser.h" +#include "dosisms.h" +#include "crc.h" + +#include "net_comx.c" + +// serial protocol + +#define SERIAL_PROTOCOL_VERSION 3 + +// The serial protocol is message oriented. The high level message format is +// a one byte message type (MTYPE_xxx), data, and a 16-bit checksum. All +// multi-byte fields are sent in network byte order. There are currently 4 +// MTYPEs defined. Their formats are as follows: +// +// MTYPE_RELIABLE sequence data_length data checksum eom +// MTYPE_UNRELIABLE sequence data_length data checksum eom +// MTYPE_ACK sequence checksum eom +// MTYPE_CONTROL data_length data checksum eom +// +// sequence is an 8-bit unsigned value starting from 0 +// data_length is a 16-bit unsigned value; it is the length of the data only +// the checksum is a 16-bit value. the CRC formula used is defined in crc.h. +// the checksum covers the entire messages, excluding itself +// eom is a special 2 byte sequence used to mark the End Of Message. This is +// needed for error recovery. +// +// A lot of behavior is based on knowledge of the upper level Quake network +// layer. For example, only one reliable message can be outstanding (pending +// reception of an MTYPE_ACK) at a time. +// +// The low level routines used to communicate with the modem are not part of +// this protocol. +// +// The CONTROL messages are only used for session establishment. They are +// not reliable or sequenced. + +#define MTYPE_RELIABLE 0x01 +#define MTYPE_UNRELIABLE 0x02 +#define MTYPE_CONTROL 0x03 +#define MTYPE_ACK 0x04 +#define MTYPE_CLIENT 0x80 + +#define ESCAPE_COMMAND 0xe0 +#define ESCAPE_EOM 0x19 + +static qboolean listening = false; + + +typedef struct SerialLine_s +{ + struct SerialLine_s *next; + qsocket_t *sock; + int lengthStated; + int lengthFound; + int tty; + qboolean connected; + qboolean connecting; + qboolean client; + double connect_time; + unsigned short crcStated; + unsigned short crcValue; + byte currState; + byte prevState; + byte mtype; + byte sequence; +} SerialLine; + +#define STATE_READY 0 +#define STATE_SEQUENCE 1 +#define STATE_LENGTH1 2 +#define STATE_LENGTH2 3 +#define STATE_DATA 4 +#define STATE_CRC1 5 +#define STATE_CRC2 6 +#define STATE_EOM 7 +#define STATE_ESCAPE 8 +#define STATE_ABORT 9 + +SerialLine serialLine[NUM_COM_PORTS]; + +int myDriverLevel; + +static void Serial_SendACK (SerialLine *p, byte sequence); + + +static void ResetSerialLineProtocol (SerialLine *p) +{ + p->connected = false; + p->connecting = false; + p->currState = STATE_READY; + p->prevState = STATE_READY; + p->lengthFound = 0; +} + + +static int ProcessInQueue(SerialLine *p) +{ + int b; + + while (1) + { + b = TTY_ReadByte(p->tty); + if (b == ERR_TTY_NODATA) + break; + + if (b == ERR_TTY_LINE_STATUS) + { + p->currState = STATE_ABORT; + continue; + } + if (b == ERR_TTY_MODEM_STATUS) + { + p->currState = STATE_ABORT; + return -1; + } + + if (b == ESCAPE_COMMAND) + if (p->currState != STATE_ESCAPE) + { + p->prevState = p->currState; + p->currState = STATE_ESCAPE; + continue; + } + + if (p->currState == STATE_ESCAPE) + { + if (b == ESCAPE_EOM) + { + if (p->prevState == STATE_ABORT) + { + p->currState = STATE_READY; + p->lengthFound = 0; + continue; + } + + if (p->prevState != STATE_EOM) + { + p->currState = STATE_READY; + p->lengthFound = 0; + Con_DPrintf("Serial: premature EOM\n"); + continue; + } + + switch (p->mtype) + { + case MTYPE_RELIABLE: + Con_DPrintf("Serial: sending ack %u\n", p->sequence); + Serial_SendACK (p, p->sequence); + if (p->sequence == p->sock->receiveSequence) + { + p->sock->receiveSequence = (p->sequence + 1) & 0xff; + p->sock->receiveMessageLength += p->lengthFound; + } + else + Con_DPrintf("Serial: reliable out of order; got %u wanted %u\n", p->sequence, p->sock->receiveSequence); + break; + + case MTYPE_UNRELIABLE: + p->sock->unreliableReceiveSequence = (p->sequence + 1) & 0xff; + p->sock->receiveMessageLength += p->lengthFound; + break; + + case MTYPE_ACK: + Con_DPrintf("Serial: got ack %u\n", p->sequence); + if (p->sequence == p->sock->sendSequence) + { + p->sock->sendSequence = (p->sock->sendSequence + 1) & 0xff; + p->sock->canSend = true; + } + else + Con_DPrintf("Serial: ack out of order; got %u wanted %u\n",p->sequence, p->sock->sendSequence); + break; + + case MTYPE_CONTROL: + p->sock->receiveMessageLength += p->lengthFound; + break; + } + + p->currState = STATE_READY; + p->lengthFound = 0; + continue; + } + + + if (b != ESCAPE_COMMAND) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad escape sequence\n"); + continue; + } + + // b == ESCAPE_COMMAND + p->currState = p->prevState; + } + + p->prevState = p->currState; + +//DEBUG + if (p->sock->receiveMessageLength + p->lengthFound > NET_MAXMESSAGE) + { + Con_DPrintf("Serial blew out receive buffer: %u\n", p->sock->receiveMessageLength + p->lengthFound); + p->currState = STATE_ABORT; + } + if (p->sock->receiveMessageLength + p->lengthFound == NET_MAXMESSAGE) + { + Con_DPrintf("Serial hit receive buffer limit: %u\n", p->sock->receiveMessageLength + p->lengthFound); + p->currState = STATE_ABORT; + } +//end DEBUG + + switch (p->currState) + { + case STATE_READY: + CRC_Init(&p->crcValue); + CRC_ProcessByte(&p->crcValue, b); + if (p->client) + { + if ((b & MTYPE_CLIENT) != 0) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: client got own message\n"); + break; + } + } + else + { + if ((b & MTYPE_CLIENT) == 0) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: server got own message\n"); + break; + } + b &= 0x7f; + } + p->mtype = b; + if (b != MTYPE_CONTROL) + p->currState = STATE_SEQUENCE; + else + p->currState = STATE_LENGTH1; + if (p->mtype < MTYPE_ACK) + { + p->sock->receiveMessage[p->sock->receiveMessageLength] = b; + p->lengthFound++; + } + break; + + case STATE_SEQUENCE: + p->sequence = b; + CRC_ProcessByte(&p->crcValue, b); + if (p->mtype != MTYPE_ACK) + p->currState = STATE_LENGTH1; + else + p->currState = STATE_CRC1; + break; + + case STATE_LENGTH1: + p->lengthStated = b * 256; + CRC_ProcessByte(&p->crcValue, b); + p->currState = STATE_LENGTH2; + break; + + case STATE_LENGTH2: + p->lengthStated += b; + CRC_ProcessByte(&p->crcValue, b); + if (p->mtype == MTYPE_RELIABLE && p->lengthStated > MAX_MSGLEN) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: bad reliable message length %u\n", p->lengthStated); + } + else if (p->mtype == MTYPE_UNRELIABLE && p->lengthStated > MAX_DATAGRAM) + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: bad unreliable message length %u\n", p->lengthStated); + } + else + { + p->currState = STATE_DATA; + if (p->mtype < MTYPE_ACK) + { + *(short *)&p->sock->receiveMessage [p->sock->receiveMessageLength + 1] = p->lengthStated; + p->lengthFound += 2; + } + } + break; + + case STATE_DATA: + p->sock->receiveMessage[p->sock->receiveMessageLength + p->lengthFound] = b; + p->lengthFound++; + CRC_ProcessByte(&p->crcValue, b); + if (p->lengthFound == p->lengthStated + 3) + p->currState = STATE_CRC1; + break; + + case STATE_CRC1: + p->crcStated = b * 256; + p->currState = STATE_CRC2; + break; + + case STATE_CRC2: + p->crcStated += b; + if (p->crcStated == CRC_Value(p->crcValue)) + { + p->currState = STATE_EOM; + } + else + { + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad crc\n"); + } + break; + + case STATE_EOM: + p->currState = STATE_ABORT; + Con_DPrintf("Serial: Bad message format\n"); + break; + + case STATE_ABORT: + break; + } + } + return 0; +} + + +int Serial_Init (void) +{ + int n; + +// LATER do Win32 serial support +#ifdef _WIN32 + return -1; +#endif + + if (COM_CheckParm("-nolan")) + return -1; + if (COM_CheckParm ("-noserial")) + return -1; + + myDriverLevel = net_driverlevel; + + if (TTY_Init()) + return -1; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + serialLine[n].tty = TTY_Open(n); + ResetSerialLineProtocol (&serialLine[n]); + } + + Con_Printf("Serial driver initialized\n"); + serialAvailable = true; + + return 0; +} + + +void Serial_Shutdown (void) +{ + int n; + + for (n = 0; n < NUM_COM_PORTS; n++) + { + if (serialLine[n].connected) + Serial_Close(serialLine[n].sock); + } + + TTY_Shutdown(); +} + + +void Serial_Listen (qboolean state) +{ + listening = state; +} + + +qboolean Serial_CanSendMessage (qsocket_t *sock) +{ + return sock->canSend; +} + + +qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock) +{ + return TTY_OutputQueueIsEmpty(((SerialLine *)sock->driverdata)->tty); +} + + +int Serial_SendMessage (qsocket_t *sock, sizebuf_t *message) +{ + SerialLine *p; + int n; + unsigned short crc; + byte b; + + p = (SerialLine *)sock->driverdata; + CRC_Init (&crc); + + // message type + b = MTYPE_RELIABLE; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = p->sock->sendSequence; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); + + // mark sock as busy and save the message for possible retransmit + sock->canSend = false; + Q_memcpy(sock->sendMessage, message->data, message->cursize); + sock->sendMessageLength = message->cursize; + sock->lastSendTime = net_time; + + return 1; +} + + +static void ReSendMessage (qsocket_t *sock) +{ + sizebuf_t temp; + + Con_DPrintf("Serial: re-sending reliable\n"); + temp.data = sock->sendMessage; + temp.maxsize = sock->sendMessageLength; + temp.cursize = sock->sendMessageLength; + Serial_SendMessage (sock, &temp); +} + + +int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *message) +{ + SerialLine *p; + int n; + unsigned short crc; + byte b; + + p = (SerialLine *)sock->driverdata; + + if (!TTY_OutputQueueIsEmpty(p->tty)) + { + TTY_Flush(p->tty); + return 1; + } + + CRC_Init (&crc); + + // message type + b = MTYPE_UNRELIABLE; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = p->sock->unreliableSendSequence; + p->sock->unreliableSendSequence = (b + 1) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); + + return 1; +} + + +static void Serial_SendACK (SerialLine *p, byte sequence) +{ + unsigned short crc; + byte b; + + CRC_Init (&crc); + + // message type + b = MTYPE_ACK; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // sequence + b = sequence; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); +} + + +static void Serial_SendControlMessage (SerialLine *p, sizebuf_t *message) +{ + unsigned short crc; + int n; + byte b; + + CRC_Init (&crc); + + // message type + b = MTYPE_CONTROL; + if (p->client) + b |= MTYPE_CLIENT; + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data length + b = message->cursize >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + b = message->cursize & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + + // data + for (n = 0; n < message->cursize; n++) + { + b = message->data[n]; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + CRC_ProcessByte (&crc, b); + } + + // checksum + b = CRC_Value (crc) >> 8; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + b = CRC_Value (crc) & 0xff; + TTY_WriteByte(p->tty, b); + if (b == ESCAPE_COMMAND) + TTY_WriteByte(p->tty, b); + + // end of message + TTY_WriteByte(p->tty, ESCAPE_COMMAND); + TTY_WriteByte(p->tty, ESCAPE_EOM); + + TTY_Flush(p->tty); +} + + +static int _Serial_GetMessage (SerialLine *p) +{ + byte ret; + short length; + + if (ProcessInQueue(p)) + return -1; + + if (p->sock->receiveMessageLength == 0) + return 0; + + ret = p->sock->receiveMessage[0]; + length = *(short *)&p->sock->receiveMessage[1]; + if (ret == MTYPE_CONTROL) + ret = 1; + + SZ_Clear (&net_message); + SZ_Write (&net_message, &p->sock->receiveMessage[3], length); + + length += 3; + p->sock->receiveMessageLength -= length; + + if (p->sock->receiveMessageLength + p->lengthFound) + Q_memcpy(p->sock->receiveMessage, &p->sock->receiveMessage[length], p->sock->receiveMessageLength + p->lengthFound); + + return ret; +} + +int Serial_GetMessage (qsocket_t *sock) +{ + SerialLine *p; + int ret; + + p = (SerialLine *)sock->driverdata; + + ret = _Serial_GetMessage (p); + + if (ret == 1) + messagesReceived++; + + if (!sock->canSend) + if ((net_time - sock->lastSendTime) > 1.0) + { + ReSendMessage (sock); + sock->lastSendTime = net_time; + } + + return ret; +} + + +void Serial_Close (qsocket_t *sock) +{ + SerialLine *p = (SerialLine *)sock->driverdata; + TTY_Close(p->tty); + ResetSerialLineProtocol (p); +} + + +char *com_types[] = {"direct", "modem"}; +unsigned com_bauds[] = {9600, 14400, 19200, 28800, 57600}; + +void Serial_SearchForHosts (qboolean xmit) +{ + int n; + SerialLine *p; + + if (sv.active) + return; + + if (hostCacheCount == HOSTCACHESIZE) + return; + + // see if we've already answered + for (n = 0; n < hostCacheCount; n++) + if (Q_strcmp (hostcache[n].cname, "#") == 0) + return; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n)) + break; + if (n == NUM_COM_PORTS) + return; + p = &serialLine[n]; + + if (TTY_IsModem(p->tty)) + return; + + sprintf(hostcache[hostCacheCount].name, "COM%u", n+1); + Q_strcpy(hostcache[hostCacheCount].map, ""); + hostcache[hostCacheCount].users = 0; + hostcache[hostCacheCount].maxusers = 0; + hostcache[hostCacheCount].driver = net_driverlevel; + Q_strcpy(hostcache[hostCacheCount].cname, "#"); + hostCacheCount++; + + return; +} + + +static qsocket_t *_Serial_Connect (char *host, SerialLine *p) +{ + int ret; + double start_time; + double last_time; + + p->client = true; + if (TTY_Connect(p->tty, host)) + return NULL; + + p->sock = NET_NewQSocket (); + p->sock->driver = myDriverLevel; + if (p->sock == NULL) + { + Con_Printf("No sockets available\n"); + return NULL; + } + p->sock->driverdata = p; + + // send the connection request + start_time = SetNetTime(); + last_time = 0.0; + + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREQ_CONNECT); + MSG_WriteString(&net_message, "QUAKE"); + do + { + SetNetTime(); + if ((net_time - last_time) >= 1.0) + { + Serial_SendControlMessage (p, &net_message); + last_time = net_time; + Con_Printf("trying...\n"); SCR_UpdateScreen (); + } + ret = _Serial_GetMessage (p); + } + while (ret == 0 && (net_time - start_time) < 5.0); + + if (ret == 0) + { + Con_Printf("Unable to connect, no response\n"); + goto ErrorReturn; + } + + if (ret == -1) + { + Con_Printf("Connection request error\n"); + goto ErrorReturn; + } + + MSG_BeginReading (); + ret = MSG_ReadByte(); + if (ret == CCREP_REJECT) + { + Con_Printf(MSG_ReadString()); + goto ErrorReturn; + } + if (ret != CCREP_ACCEPT) + { + Con_Printf("Unknown connection response\n"); + goto ErrorReturn; + } + + p->connected = true; + p->sock->lastMessageTime = net_time; + + Con_Printf ("Connection accepted\n"); + + return p->sock; + +ErrorReturn: + TTY_Disconnect(p->tty); + return NULL; +} + +qsocket_t *Serial_Connect (char *host) +{ + int n; + qsocket_t *ret = NULL; + + // see if this looks like a phone number + if (*host == '#') + host++; + for (n = 0; n < Q_strlen(host); n++) + if (host[n] == '.' || host[n] == ':') + return NULL; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n) && !serialLine[n].connected) + if ((ret = _Serial_Connect (host, &serialLine[n]))) + break; + return ret; +} + + +static qsocket_t *_Serial_CheckNewConnections (SerialLine *p) +{ + int command; + + p->client = false; + if (!TTY_CheckForConnection(p->tty)) + return NULL; + + if (TTY_IsModem(p->tty)) + { + if (!p->connecting) + { + p->connecting = true; + p->connect_time = net_time; + } + else if ((net_time - p->connect_time) > 15.0) + { + p->connecting = false; + TTY_Disconnect(p->tty); + return NULL; + } + } + + p->sock = NET_NewQSocket (); + p->sock->driver = myDriverLevel; + if (p->sock == NULL) + { + Con_Printf("No sockets available\n"); + return NULL; + } + p->sock->driverdata = p; + + SZ_Clear(&net_message); + if (_Serial_GetMessage(p) != 1) + { + NET_FreeQSocket(p->sock); + return NULL; + } + + MSG_BeginReading (); + command = MSG_ReadByte(); + + if (command == CCREQ_SERVER_INFO) + { + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + if (MSG_ReadByte() != SERIAL_PROTOCOL_VERSION) + return NULL; + + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREP_SERVER_INFO); + MSG_WriteString(&net_message, hostname.string); + MSG_WriteString(&net_message, sv.name); + MSG_WriteByte(&net_message, net_activeconnections); + MSG_WriteByte(&net_message, svs.maxclients); + Serial_SendControlMessage (p, &net_message); + SZ_Clear(&net_message); + return NULL; + } + + if (command != CCREQ_CONNECT) + return NULL; + + if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + // send him back the info about the server connection he has been allocated + SZ_Clear(&net_message); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + Serial_SendControlMessage (p, &net_message); + SZ_Clear(&net_message); + + p->connected = true; + p->connecting = false; + p->sock->lastMessageTime = net_time; + sprintf(p->sock->address, "COM%u", (int)((p - serialLine) + 1)); + + return p->sock; +} + +qsocket_t *Serial_CheckNewConnections (void) +{ + int n; + qsocket_t *ret = NULL; + + for (n = 0; n < NUM_COM_PORTS; n++) + if (TTY_IsEnabled(n) && !serialLine[n].connected) + if ((ret = _Serial_CheckNewConnections (&serialLine[n]))) + break; + return ret; +} diff --git a/WinQuake/net_ser.h b/WinQuake/net_ser.h index 5885ab9..250394f 100644 --- a/WinQuake/net_ser.h +++ b/WinQuake/net_ser.h @@ -1,33 +1,33 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_ser.h - -int Serial_Init (void); -void Serial_Listen (qboolean state); -void Serial_SearchForHosts (qboolean xmit); -qsocket_t *Serial_Connect (char *host); -qsocket_t *Serial_CheckNewConnections (void); -int Serial_GetMessage (qsocket_t *sock); -int Serial_SendMessage (qsocket_t *sock, sizebuf_t *data); -int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Serial_CanSendMessage (qsocket_t *sock); -qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock); -void Serial_Close (qsocket_t *sock); -void Serial_Shutdown (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_ser.h + +int Serial_Init (void); +void Serial_Listen (qboolean state); +void Serial_SearchForHosts (qboolean xmit); +qsocket_t *Serial_Connect (char *host); +qsocket_t *Serial_CheckNewConnections (void); +int Serial_GetMessage (qsocket_t *sock); +int Serial_SendMessage (qsocket_t *sock, sizebuf_t *data); +int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); +qboolean Serial_CanSendMessage (qsocket_t *sock); +qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock); +void Serial_Close (qsocket_t *sock); +void Serial_Shutdown (void); diff --git a/WinQuake/net_udp.c b/WinQuake/net_udp.c index 3eded99..f23e4ef 100644 --- a/WinQuake/net_udp.c +++ b/WinQuake/net_udp.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // net_udp.c #include "quakedef.h" diff --git a/WinQuake/net_udp.h b/WinQuake/net_udp.h index 7530301..b1cbcdb 100644 --- a/WinQuake/net_udp.h +++ b/WinQuake/net_udp.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_udp.h - -int UDP_Init (void); -void UDP_Shutdown (void); -void UDP_Listen (qboolean state); -int UDP_OpenSocket (int port); -int UDP_CloseSocket (int socket); -int UDP_Connect (int socket, struct qsockaddr *addr); -int UDP_CheckNewConnections (void); -int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int UDP_Broadcast (int socket, byte *buf, int len); -char *UDP_AddrToString (struct qsockaddr *addr); -int UDP_StringToAddr (char *string, struct qsockaddr *addr); -int UDP_GetSocketAddr (int socket, struct qsockaddr *addr); -int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name); -int UDP_GetAddrFromName (char *name, struct qsockaddr *addr); -int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int UDP_GetSocketPort (struct qsockaddr *addr); -int UDP_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_udp.h + +int UDP_Init (void); +void UDP_Shutdown (void); +void UDP_Listen (qboolean state); +int UDP_OpenSocket (int port); +int UDP_CloseSocket (int socket); +int UDP_Connect (int socket, struct qsockaddr *addr); +int UDP_CheckNewConnections (void); +int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int UDP_Broadcast (int socket, byte *buf, int len); +char *UDP_AddrToString (struct qsockaddr *addr); +int UDP_StringToAddr (char *string, struct qsockaddr *addr); +int UDP_GetSocketAddr (int socket, struct qsockaddr *addr); +int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name); +int UDP_GetAddrFromName (char *name, struct qsockaddr *addr); +int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int UDP_GetSocketPort (struct qsockaddr *addr); +int UDP_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/net_vcr.c b/WinQuake/net_vcr.c index ba8f40d..2833909 100644 --- a/WinQuake/net_vcr.c +++ b/WinQuake/net_vcr.c @@ -1,167 +1,167 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_vcr.c - -#include "quakedef.h" -#include "net_vcr.h" - -extern int vcrFile; - -// This is the playback portion of the VCR. It reads the file produced -// by the recorder and plays it back to the host. The recording contains -// everything necessary (events, timestamps, and data) to duplicate the game -// from the viewpoint of everything above the network layer. - -static struct -{ - double time; - int op; - long session; -} next; - -int VCR_Init (void) -{ - net_drivers[0].Init = VCR_Init; - - net_drivers[0].SearchForHosts = VCR_SearchForHosts; - net_drivers[0].Connect = VCR_Connect; - net_drivers[0].CheckNewConnections = VCR_CheckNewConnections; - net_drivers[0].QGetMessage = VCR_GetMessage; - net_drivers[0].QSendMessage = VCR_SendMessage; - net_drivers[0].CanSendMessage = VCR_CanSendMessage; - net_drivers[0].Close = VCR_Close; - net_drivers[0].Shutdown = VCR_Shutdown; - - Sys_FileRead(vcrFile, &next, sizeof(next)); - return 0; -} - -void VCR_ReadNext (void) -{ - if (Sys_FileRead(vcrFile, &next, sizeof(next)) == 0) - { - next.op = 255; - Sys_Error ("=== END OF PLAYBACK===\n"); - } - if (next.op < 1 || next.op > VCR_MAX_MESSAGE) - Sys_Error ("VCR_ReadNext: bad op"); -} - - -void VCR_Listen (qboolean state) -{ -} - - -void VCR_Shutdown (void) -{ -} - - -int VCR_GetMessage (qsocket_t *sock) -{ - int ret; - - if (host_time != next.time || next.op != VCR_OP_GETMESSAGE || next.session != *(long *)(&sock->driverdata)) - Sys_Error ("VCR missmatch"); - - Sys_FileRead(vcrFile, &ret, sizeof(int)); - if (ret != 1) - { - VCR_ReadNext (); - return ret; - } - - Sys_FileRead(vcrFile, &net_message.cursize, sizeof(int)); - Sys_FileRead(vcrFile, net_message.data, net_message.cursize); - - VCR_ReadNext (); - - return 1; -} - - -int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - int ret; - - if (host_time != next.time || next.op != VCR_OP_SENDMESSAGE || next.session != *(long *)(&sock->driverdata)) - Sys_Error ("VCR missmatch"); - - Sys_FileRead(vcrFile, &ret, sizeof(int)); - - VCR_ReadNext (); - - return ret; -} - - -qboolean VCR_CanSendMessage (qsocket_t *sock) -{ - qboolean ret; - - if (host_time != next.time || next.op != VCR_OP_CANSENDMESSAGE || next.session != *(long *)(&sock->driverdata)) - Sys_Error ("VCR missmatch"); - - Sys_FileRead(vcrFile, &ret, sizeof(int)); - - VCR_ReadNext (); - - return ret; -} - - -void VCR_Close (qsocket_t *sock) -{ -} - - -void VCR_SearchForHosts (qboolean xmit) -{ -} - - -qsocket_t *VCR_Connect (char *host) -{ - return NULL; -} - - -qsocket_t *VCR_CheckNewConnections (void) -{ - qsocket_t *sock; - - if (host_time != next.time || next.op != VCR_OP_CONNECT) - Sys_Error ("VCR missmatch"); - - if (!next.session) - { - VCR_ReadNext (); - return NULL; - } - - sock = NET_NewQSocket (); - *(long *)(&sock->driverdata) = next.session; - - Sys_FileRead (vcrFile, sock->address, NET_NAMELEN); - VCR_ReadNext (); - - return sock; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_vcr.c + +#include "quakedef.h" +#include "net_vcr.h" + +extern int vcrFile; + +// This is the playback portion of the VCR. It reads the file produced +// by the recorder and plays it back to the host. The recording contains +// everything necessary (events, timestamps, and data) to duplicate the game +// from the viewpoint of everything above the network layer. + +static struct +{ + double time; + int op; + long session; +} next; + +int VCR_Init (void) +{ + net_drivers[0].Init = VCR_Init; + + net_drivers[0].SearchForHosts = VCR_SearchForHosts; + net_drivers[0].Connect = VCR_Connect; + net_drivers[0].CheckNewConnections = VCR_CheckNewConnections; + net_drivers[0].QGetMessage = VCR_GetMessage; + net_drivers[0].QSendMessage = VCR_SendMessage; + net_drivers[0].CanSendMessage = VCR_CanSendMessage; + net_drivers[0].Close = VCR_Close; + net_drivers[0].Shutdown = VCR_Shutdown; + + Sys_FileRead(vcrFile, &next, sizeof(next)); + return 0; +} + +void VCR_ReadNext (void) +{ + if (Sys_FileRead(vcrFile, &next, sizeof(next)) == 0) + { + next.op = 255; + Sys_Error ("=== END OF PLAYBACK===\n"); + } + if (next.op < 1 || next.op > VCR_MAX_MESSAGE) + Sys_Error ("VCR_ReadNext: bad op"); +} + + +void VCR_Listen (qboolean state) +{ +} + + +void VCR_Shutdown (void) +{ +} + + +int VCR_GetMessage (qsocket_t *sock) +{ + int ret; + + if (host_time != next.time || next.op != VCR_OP_GETMESSAGE || next.session != *(long *)(&sock->driverdata)) + Sys_Error ("VCR missmatch"); + + Sys_FileRead(vcrFile, &ret, sizeof(int)); + if (ret != 1) + { + VCR_ReadNext (); + return ret; + } + + Sys_FileRead(vcrFile, &net_message.cursize, sizeof(int)); + Sys_FileRead(vcrFile, net_message.data, net_message.cursize); + + VCR_ReadNext (); + + return 1; +} + + +int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + int ret; + + if (host_time != next.time || next.op != VCR_OP_SENDMESSAGE || next.session != *(long *)(&sock->driverdata)) + Sys_Error ("VCR missmatch"); + + Sys_FileRead(vcrFile, &ret, sizeof(int)); + + VCR_ReadNext (); + + return ret; +} + + +qboolean VCR_CanSendMessage (qsocket_t *sock) +{ + qboolean ret; + + if (host_time != next.time || next.op != VCR_OP_CANSENDMESSAGE || next.session != *(long *)(&sock->driverdata)) + Sys_Error ("VCR missmatch"); + + Sys_FileRead(vcrFile, &ret, sizeof(int)); + + VCR_ReadNext (); + + return ret; +} + + +void VCR_Close (qsocket_t *sock) +{ +} + + +void VCR_SearchForHosts (qboolean xmit) +{ +} + + +qsocket_t *VCR_Connect (char *host) +{ + return NULL; +} + + +qsocket_t *VCR_CheckNewConnections (void) +{ + qsocket_t *sock; + + if (host_time != next.time || next.op != VCR_OP_CONNECT) + Sys_Error ("VCR missmatch"); + + if (!next.session) + { + VCR_ReadNext (); + return NULL; + } + + sock = NET_NewQSocket (); + *(long *)(&sock->driverdata) = next.session; + + Sys_FileRead (vcrFile, sock->address, NET_NAMELEN); + VCR_ReadNext (); + + return sock; +} diff --git a/WinQuake/net_vcr.h b/WinQuake/net_vcr.h index 95c2f34..2374697 100644 --- a/WinQuake/net_vcr.h +++ b/WinQuake/net_vcr.h @@ -1,37 +1,37 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_vcr.h - -#define VCR_OP_CONNECT 1 -#define VCR_OP_GETMESSAGE 2 -#define VCR_OP_SENDMESSAGE 3 -#define VCR_OP_CANSENDMESSAGE 4 -#define VCR_MAX_MESSAGE 4 - -int VCR_Init (void); -void VCR_Listen (qboolean state); -void VCR_SearchForHosts (qboolean xmit); -qsocket_t *VCR_Connect (char *host); -qsocket_t *VCR_CheckNewConnections (void); -int VCR_GetMessage (qsocket_t *sock); -int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data); -qboolean VCR_CanSendMessage (qsocket_t *sock); -void VCR_Close (qsocket_t *sock); -void VCR_Shutdown (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_vcr.h + +#define VCR_OP_CONNECT 1 +#define VCR_OP_GETMESSAGE 2 +#define VCR_OP_SENDMESSAGE 3 +#define VCR_OP_CANSENDMESSAGE 4 +#define VCR_MAX_MESSAGE 4 + +int VCR_Init (void); +void VCR_Listen (qboolean state); +void VCR_SearchForHosts (qboolean xmit); +qsocket_t *VCR_Connect (char *host); +qsocket_t *VCR_CheckNewConnections (void); +int VCR_GetMessage (qsocket_t *sock); +int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data); +qboolean VCR_CanSendMessage (qsocket_t *sock); +void VCR_Close (qsocket_t *sock); +void VCR_Shutdown (void); diff --git a/WinQuake/net_win.c b/WinQuake/net_win.c index 9c9e6cb..242cc16 100644 --- a/WinQuake/net_win.c +++ b/WinQuake/net_win.c @@ -1,120 +1,120 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -#include "net_loop.h" -#include "net_dgrm.h" -#include "net_ser.h" - -net_driver_t net_drivers[MAX_NET_DRIVERS] = -{ - { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown - } - , - { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown - } -}; - -int net_numdrivers = 2; - - -#include "net_wins.h" -#include "net_wipx.h" - -net_landriver_t net_landrivers[MAX_NET_DRIVERS] = -{ - { - "Winsock TCPIP", - false, - 0, - WINS_Init, - WINS_Shutdown, - WINS_Listen, - WINS_OpenSocket, - WINS_CloseSocket, - WINS_Connect, - WINS_CheckNewConnections, - WINS_Read, - WINS_Write, - WINS_Broadcast, - WINS_AddrToString, - WINS_StringToAddr, - WINS_GetSocketAddr, - WINS_GetNameFromAddr, - WINS_GetAddrFromName, - WINS_AddrCompare, - WINS_GetSocketPort, - WINS_SetSocketPort - }, - { - "Winsock IPX", - false, - 0, - WIPX_Init, - WIPX_Shutdown, - WIPX_Listen, - WIPX_OpenSocket, - WIPX_CloseSocket, - WIPX_Connect, - WIPX_CheckNewConnections, - WIPX_Read, - WIPX_Write, - WIPX_Broadcast, - WIPX_AddrToString, - WIPX_StringToAddr, - WIPX_GetSocketAddr, - WIPX_GetNameFromAddr, - WIPX_GetAddrFromName, - WIPX_AddrCompare, - WIPX_GetSocketPort, - WIPX_SetSocketPort - } - -}; - -int net_numlandrivers = 2; +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" + +#include "net_loop.h" +#include "net_dgrm.h" +#include "net_ser.h" + +net_driver_t net_drivers[MAX_NET_DRIVERS] = +{ + { + "Loopback", + false, + Loop_Init, + Loop_Listen, + Loop_SearchForHosts, + Loop_Connect, + Loop_CheckNewConnections, + Loop_GetMessage, + Loop_SendMessage, + Loop_SendUnreliableMessage, + Loop_CanSendMessage, + Loop_CanSendUnreliableMessage, + Loop_Close, + Loop_Shutdown + } + , + { + "Datagram", + false, + Datagram_Init, + Datagram_Listen, + Datagram_SearchForHosts, + Datagram_Connect, + Datagram_CheckNewConnections, + Datagram_GetMessage, + Datagram_SendMessage, + Datagram_SendUnreliableMessage, + Datagram_CanSendMessage, + Datagram_CanSendUnreliableMessage, + Datagram_Close, + Datagram_Shutdown + } +}; + +int net_numdrivers = 2; + + +#include "net_wins.h" +#include "net_wipx.h" + +net_landriver_t net_landrivers[MAX_NET_DRIVERS] = +{ + { + "Winsock TCPIP", + false, + 0, + WINS_Init, + WINS_Shutdown, + WINS_Listen, + WINS_OpenSocket, + WINS_CloseSocket, + WINS_Connect, + WINS_CheckNewConnections, + WINS_Read, + WINS_Write, + WINS_Broadcast, + WINS_AddrToString, + WINS_StringToAddr, + WINS_GetSocketAddr, + WINS_GetNameFromAddr, + WINS_GetAddrFromName, + WINS_AddrCompare, + WINS_GetSocketPort, + WINS_SetSocketPort + }, + { + "Winsock IPX", + false, + 0, + WIPX_Init, + WIPX_Shutdown, + WIPX_Listen, + WIPX_OpenSocket, + WIPX_CloseSocket, + WIPX_Connect, + WIPX_CheckNewConnections, + WIPX_Read, + WIPX_Write, + WIPX_Broadcast, + WIPX_AddrToString, + WIPX_StringToAddr, + WIPX_GetSocketAddr, + WIPX_GetNameFromAddr, + WIPX_GetAddrFromName, + WIPX_AddrCompare, + WIPX_GetSocketPort, + WIPX_SetSocketPort + } + +}; + +int net_numlandrivers = 2; diff --git a/WinQuake/net_wins.c b/WinQuake/net_wins.c index 3d188ed..5c24b10 100644 --- a/WinQuake/net_wins.c +++ b/WinQuake/net_wins.c @@ -1,575 +1,575 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_wins.c - -#include "quakedef.h" -#include "winquake.h" - -extern cvar_t hostname; - -#define MAXHOSTNAMELEN 256 - -static int net_acceptsocket = -1; // socket for fielding new connections -static int net_controlsocket; -static int net_broadcastsocket = 0; -static struct qsockaddr broadcastaddr; - -static unsigned long myAddr; - -qboolean winsock_lib_initialized; - -int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); -int (PASCAL FAR *pWSACleanup)(void); -int (PASCAL FAR *pWSAGetLastError)(void); -SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); -int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); -int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, - const char FAR * optval, int optlen); -int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, - struct sockaddr FAR *from, int FAR * fromlen); -int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, - const struct sockaddr FAR *to, int tolen); -int (PASCAL FAR *pclosesocket)(SOCKET s); -int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); -struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); -struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, - int len, int type); -int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, - int FAR * namelen); - -#include "net_wins.h" - -int winsock_initialized = 0; -WSADATA winsockdata; - -//============================================================================= - -static double blocktime; - -BOOL PASCAL FAR BlockingHook(void) -{ - MSG msg; - BOOL ret; - - if ((Sys_FloatTime() - blocktime) > 2.0) - { - WSACancelBlockingCall(); - return FALSE; - } - - /* get the next message, if any */ - ret = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); - - /* if we got one, process it */ - if (ret) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - /* TRUE if we got a message */ - return ret; -} - - -void WINS_GetLocalAddress() -{ - struct hostent *local = NULL; - char buff[MAXHOSTNAMELEN]; - unsigned long addr; - - if (myAddr != INADDR_ANY) - return; - - if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) - return; - - blocktime = Sys_FloatTime(); - WSASetBlockingHook(BlockingHook); - local = pgethostbyname(buff); - WSAUnhookBlockingHook(); - if (local == NULL) - return; - - myAddr = *(int *)local->h_addr_list[0]; - - addr = ntohl(myAddr); - sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); -} - - -int WINS_Init (void) -{ - int i; - char buff[MAXHOSTNAMELEN]; - char *p; - int r; - WORD wVersionRequested; - HINSTANCE hInst; - -// initialize the Winsock function vectors (we do this instead of statically linking -// so we can run on Win 3.1, where there isn't necessarily Winsock) - hInst = LoadLibrary("wsock32.dll"); - - if (hInst == NULL) - { - Con_SafePrintf ("Failed to load winsock.dll\n"); - winsock_lib_initialized = false; - return -1; - } - - winsock_lib_initialized = true; - - pWSAStartup = (void *)GetProcAddress(hInst, "WSAStartup"); - pWSACleanup = (void *)GetProcAddress(hInst, "WSACleanup"); - pWSAGetLastError = (void *)GetProcAddress(hInst, "WSAGetLastError"); - psocket = (void *)GetProcAddress(hInst, "socket"); - pioctlsocket = (void *)GetProcAddress(hInst, "ioctlsocket"); - psetsockopt = (void *)GetProcAddress(hInst, "setsockopt"); - precvfrom = (void *)GetProcAddress(hInst, "recvfrom"); - psendto = (void *)GetProcAddress(hInst, "sendto"); - pclosesocket = (void *)GetProcAddress(hInst, "closesocket"); - pgethostname = (void *)GetProcAddress(hInst, "gethostname"); - pgethostbyname = (void *)GetProcAddress(hInst, "gethostbyname"); - pgethostbyaddr = (void *)GetProcAddress(hInst, "gethostbyaddr"); - pgetsockname = (void *)GetProcAddress(hInst, "getsockname"); - - if (!pWSAStartup || !pWSACleanup || !pWSAGetLastError || - !psocket || !pioctlsocket || !psetsockopt || - !precvfrom || !psendto || !pclosesocket || - !pgethostname || !pgethostbyname || !pgethostbyaddr || - !pgetsockname) - { - Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n"); - return -1; - } - - if (COM_CheckParm ("-noudp")) - return -1; - - if (winsock_initialized == 0) - { - wVersionRequested = MAKEWORD(1, 1); - - r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); - - if (r) - { - Con_SafePrintf ("Winsock initialization failed.\n"); - return -1; - } - } - winsock_initialized++; - - // determine my name - if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) - { - Con_DPrintf ("Winsock TCP/IP Initialization failed.\n"); - if (--winsock_initialized == 0) - pWSACleanup (); - return -1; - } - - // if the quake hostname isn't set, set it to the machine name - if (Q_strcmp(hostname.string, "UNNAMED") == 0) - { - // see if it's a text IP address (well, close enough) - for (p = buff; *p; p++) - if ((*p < '0' || *p > '9') && *p != '.') - break; - - // if it is a real name, strip off the domain; we only want the host - if (*p) - { - for (i = 0; i < 15; i++) - if (buff[i] == '.') - break; - buff[i] = 0; - } - Cvar_Set ("hostname", buff); - } - - i = COM_CheckParm ("-ip"); - if (i) - { - if (i < com_argc-1) - { - myAddr = inet_addr(com_argv[i+1]); - if (myAddr == INADDR_NONE) - Sys_Error ("%s is not a valid IP address", com_argv[i+1]); - strcpy(my_tcpip_address, com_argv[i+1]); - } - else - { - Sys_Error ("NET_Init: you must specify an IP address after -ip"); - } - } - else - { - myAddr = INADDR_ANY; - strcpy(my_tcpip_address, "INADDR_ANY"); - } - - if ((net_controlsocket = WINS_OpenSocket (0)) == -1) - { - Con_Printf("WINS_Init: Unable to open control socket\n"); - if (--winsock_initialized == 0) - pWSACleanup (); - return -1; - } - - ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; - ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; - ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); - - Con_Printf("Winsock TCP/IP Initialized\n"); - tcpipAvailable = true; - - return net_controlsocket; -} - -//============================================================================= - -void WINS_Shutdown (void) -{ - WINS_Listen (false); - WINS_CloseSocket (net_controlsocket); - if (--winsock_initialized == 0) - pWSACleanup (); -} - -//============================================================================= - -void WINS_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - WINS_GetLocalAddress(); - if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1) - Sys_Error ("WINS_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - WINS_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - -//============================================================================= - -int WINS_OpenSocket (int port) -{ - int newsocket; - struct sockaddr_in address; - u_long _true = 1; - - if ((newsocket = psocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - return -1; - - if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) - goto ErrorReturn; - - address.sin_family = AF_INET; - address.sin_addr.s_addr = myAddr; - address.sin_port = htons((unsigned short)port); - if( bind (newsocket, (void *)&address, sizeof(address)) == 0) - return newsocket; - - Sys_Error ("Unable to bind to %s", WINS_AddrToString((struct qsockaddr *)&address)); -ErrorReturn: - pclosesocket (newsocket); - return -1; -} - -//============================================================================= - -int WINS_CloseSocket (int socket) -{ - if (socket == net_broadcastsocket) - net_broadcastsocket = 0; - return pclosesocket (socket); -} - - -//============================================================================= -/* -============ -PartialIPAddress - -this lets you type only as much of the net address as required, using -the local network components to fill in the rest -============ -*/ -static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) -{ - char buff[256]; - char *b; - int addr; - int num; - int mask; - int run; - int port; - - buff[0] = '.'; - b = buff; - strcpy(buff+1, in); - if (buff[1] == '.') - b++; - - addr = 0; - mask=-1; - while (*b == '.') - { - b++; - num = 0; - run = 0; - while (!( *b < '0' || *b > '9')) - { - num = num*10 + *b++ - '0'; - if (++run > 3) - return -1; - } - if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) - return -1; - if (num < 0 || num > 255) - return -1; - mask<<=8; - addr = (addr<<8) + num; - } - - if (*b++ == ':') - port = Q_atoi(b); - else - port = net_hostport; - - hostaddr->sa_family = AF_INET; - ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); - ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); - - return 0; -} -//============================================================================= - -int WINS_Connect (int socket, struct qsockaddr *addr) -{ - return 0; -} - -//============================================================================= - -int WINS_CheckNewConnections (void) -{ - char buf[4096]; - - if (net_acceptsocket == -1) - return -1; - - if (precvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) > 0) - { - return net_acceptsocket; - } - return -1; -} - -//============================================================================= - -int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr) -{ - int addrlen = sizeof (struct qsockaddr); - int ret; - - ret = precvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); - if (ret == -1) - { - int errno = pWSAGetLastError(); - - if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) - return 0; - - } - return ret; -} - -//============================================================================= - -int WINS_MakeSocketBroadcastCapable (int socket) -{ - int i = 1; - - // make this socket broadcast capable - if (psetsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) - return -1; - net_broadcastsocket = socket; - - return 0; -} - -//============================================================================= - -int WINS_Broadcast (int socket, byte *buf, int len) -{ - int ret; - - if (socket != net_broadcastsocket) - { - if (net_broadcastsocket != 0) - Sys_Error("Attempted to use multiple broadcasts sockets\n"); - WINS_GetLocalAddress(); - ret = WINS_MakeSocketBroadcastCapable (socket); - if (ret == -1) - { - Con_Printf("Unable to make socket broadcast capable\n"); - return ret; - } - } - - return WINS_Write (socket, buf, len, &broadcastaddr); -} - -//============================================================================= - -int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr) -{ - int ret; - - ret = psendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); - if (ret == -1) - if (pWSAGetLastError() == WSAEWOULDBLOCK) - return 0; - - return ret; -} - -//============================================================================= - -char *WINS_AddrToString (struct qsockaddr *addr) -{ - static char buffer[22]; - int haddr; - - haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); - sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); - return buffer; -} - -//============================================================================= - -int WINS_StringToAddr (char *string, struct qsockaddr *addr) -{ - int ha1, ha2, ha3, ha4, hp; - int ipaddr; - - sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); - ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp); - return 0; -} - -//============================================================================= - -int WINS_GetSocketAddr (int socket, struct qsockaddr *addr) -{ - int addrlen = sizeof(struct qsockaddr); - unsigned int a; - - Q_memset(addr, 0, sizeof(struct qsockaddr)); - pgetsockname(socket, (struct sockaddr *)addr, &addrlen); - a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; - if (a == 0 || a == inet_addr("127.0.0.1")) - ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; - - return 0; -} - -//============================================================================= - -int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name) -{ - struct hostent *hostentry; - - hostentry = pgethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); - if (hostentry) - { - Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); - return 0; - } - - Q_strcpy (name, WINS_AddrToString (addr)); - return 0; -} - -//============================================================================= - -int WINS_GetAddrFromName(char *name, struct qsockaddr *addr) -{ - struct hostent *hostentry; - - if (name[0] >= '0' && name[0] <= '9') - return PartialIPAddress (name, addr); - - hostentry = pgethostbyname (name); - if (!hostentry) - return -1; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport); - ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; - - return 0; -} - -//============================================================================= - -int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) - return 1; - - return 0; -} - -//============================================================================= - -int WINS_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_in *)addr)->sin_port); -} - - -int WINS_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port); - return 0; -} - -//============================================================================= +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_wins.c + +#include "quakedef.h" +#include "winquake.h" + +extern cvar_t hostname; + +#define MAXHOSTNAMELEN 256 + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket; +static int net_broadcastsocket = 0; +static struct qsockaddr broadcastaddr; + +static unsigned long myAddr; + +qboolean winsock_lib_initialized; + +int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); +int (PASCAL FAR *pWSACleanup)(void); +int (PASCAL FAR *pWSAGetLastError)(void); +SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); +int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); +int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, + const char FAR * optval, int optlen); +int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, + struct sockaddr FAR *from, int FAR * fromlen); +int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, + const struct sockaddr FAR *to, int tolen); +int (PASCAL FAR *pclosesocket)(SOCKET s); +int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); +struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); +struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, + int len, int type); +int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, + int FAR * namelen); + +#include "net_wins.h" + +int winsock_initialized = 0; +WSADATA winsockdata; + +//============================================================================= + +static double blocktime; + +BOOL PASCAL FAR BlockingHook(void) +{ + MSG msg; + BOOL ret; + + if ((Sys_FloatTime() - blocktime) > 2.0) + { + WSACancelBlockingCall(); + return FALSE; + } + + /* get the next message, if any */ + ret = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + + /* if we got one, process it */ + if (ret) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* TRUE if we got a message */ + return ret; +} + + +void WINS_GetLocalAddress() +{ + struct hostent *local = NULL; + char buff[MAXHOSTNAMELEN]; + unsigned long addr; + + if (myAddr != INADDR_ANY) + return; + + if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) + return; + + blocktime = Sys_FloatTime(); + WSASetBlockingHook(BlockingHook); + local = pgethostbyname(buff); + WSAUnhookBlockingHook(); + if (local == NULL) + return; + + myAddr = *(int *)local->h_addr_list[0]; + + addr = ntohl(myAddr); + sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); +} + + +int WINS_Init (void) +{ + int i; + char buff[MAXHOSTNAMELEN]; + char *p; + int r; + WORD wVersionRequested; + HINSTANCE hInst; + +// initialize the Winsock function vectors (we do this instead of statically linking +// so we can run on Win 3.1, where there isn't necessarily Winsock) + hInst = LoadLibrary("wsock32.dll"); + + if (hInst == NULL) + { + Con_SafePrintf ("Failed to load winsock.dll\n"); + winsock_lib_initialized = false; + return -1; + } + + winsock_lib_initialized = true; + + pWSAStartup = (void *)GetProcAddress(hInst, "WSAStartup"); + pWSACleanup = (void *)GetProcAddress(hInst, "WSACleanup"); + pWSAGetLastError = (void *)GetProcAddress(hInst, "WSAGetLastError"); + psocket = (void *)GetProcAddress(hInst, "socket"); + pioctlsocket = (void *)GetProcAddress(hInst, "ioctlsocket"); + psetsockopt = (void *)GetProcAddress(hInst, "setsockopt"); + precvfrom = (void *)GetProcAddress(hInst, "recvfrom"); + psendto = (void *)GetProcAddress(hInst, "sendto"); + pclosesocket = (void *)GetProcAddress(hInst, "closesocket"); + pgethostname = (void *)GetProcAddress(hInst, "gethostname"); + pgethostbyname = (void *)GetProcAddress(hInst, "gethostbyname"); + pgethostbyaddr = (void *)GetProcAddress(hInst, "gethostbyaddr"); + pgetsockname = (void *)GetProcAddress(hInst, "getsockname"); + + if (!pWSAStartup || !pWSACleanup || !pWSAGetLastError || + !psocket || !pioctlsocket || !psetsockopt || + !precvfrom || !psendto || !pclosesocket || + !pgethostname || !pgethostbyname || !pgethostbyaddr || + !pgetsockname) + { + Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n"); + return -1; + } + + if (COM_CheckParm ("-noudp")) + return -1; + + if (winsock_initialized == 0) + { + wVersionRequested = MAKEWORD(1, 1); + + r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); + + if (r) + { + Con_SafePrintf ("Winsock initialization failed.\n"); + return -1; + } + } + winsock_initialized++; + + // determine my name + if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) + { + Con_DPrintf ("Winsock TCP/IP Initialization failed.\n"); + if (--winsock_initialized == 0) + pWSACleanup (); + return -1; + } + + // if the quake hostname isn't set, set it to the machine name + if (Q_strcmp(hostname.string, "UNNAMED") == 0) + { + // see if it's a text IP address (well, close enough) + for (p = buff; *p; p++) + if ((*p < '0' || *p > '9') && *p != '.') + break; + + // if it is a real name, strip off the domain; we only want the host + if (*p) + { + for (i = 0; i < 15; i++) + if (buff[i] == '.') + break; + buff[i] = 0; + } + Cvar_Set ("hostname", buff); + } + + i = COM_CheckParm ("-ip"); + if (i) + { + if (i < com_argc-1) + { + myAddr = inet_addr(com_argv[i+1]); + if (myAddr == INADDR_NONE) + Sys_Error ("%s is not a valid IP address", com_argv[i+1]); + strcpy(my_tcpip_address, com_argv[i+1]); + } + else + { + Sys_Error ("NET_Init: you must specify an IP address after -ip"); + } + } + else + { + myAddr = INADDR_ANY; + strcpy(my_tcpip_address, "INADDR_ANY"); + } + + if ((net_controlsocket = WINS_OpenSocket (0)) == -1) + { + Con_Printf("WINS_Init: Unable to open control socket\n"); + if (--winsock_initialized == 0) + pWSACleanup (); + return -1; + } + + ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; + ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); + + Con_Printf("Winsock TCP/IP Initialized\n"); + tcpipAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void WINS_Shutdown (void) +{ + WINS_Listen (false); + WINS_CloseSocket (net_controlsocket); + if (--winsock_initialized == 0) + pWSACleanup (); +} + +//============================================================================= + +void WINS_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + WINS_GetLocalAddress(); + if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1) + Sys_Error ("WINS_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + WINS_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int WINS_OpenSocket (int port) +{ + int newsocket; + struct sockaddr_in address; + u_long _true = 1; + + if ((newsocket = psocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + return -1; + + if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) + goto ErrorReturn; + + address.sin_family = AF_INET; + address.sin_addr.s_addr = myAddr; + address.sin_port = htons((unsigned short)port); + if( bind (newsocket, (void *)&address, sizeof(address)) == 0) + return newsocket; + + Sys_Error ("Unable to bind to %s", WINS_AddrToString((struct qsockaddr *)&address)); +ErrorReturn: + pclosesocket (newsocket); + return -1; +} + +//============================================================================= + +int WINS_CloseSocket (int socket) +{ + if (socket == net_broadcastsocket) + net_broadcastsocket = 0; + return pclosesocket (socket); +} + + +//============================================================================= +/* +============ +PartialIPAddress + +this lets you type only as much of the net address as required, using +the local network components to fill in the rest +============ +*/ +static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) +{ + char buff[256]; + char *b; + int addr; + int num; + int mask; + int run; + int port; + + buff[0] = '.'; + b = buff; + strcpy(buff+1, in); + if (buff[1] == '.') + b++; + + addr = 0; + mask=-1; + while (*b == '.') + { + b++; + num = 0; + run = 0; + while (!( *b < '0' || *b > '9')) + { + num = num*10 + *b++ - '0'; + if (++run > 3) + return -1; + } + if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) + return -1; + if (num < 0 || num > 255) + return -1; + mask<<=8; + addr = (addr<<8) + num; + } + + if (*b++ == ':') + port = Q_atoi(b); + else + port = net_hostport; + + hostaddr->sa_family = AF_INET; + ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); + ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); + + return 0; +} +//============================================================================= + +int WINS_Connect (int socket, struct qsockaddr *addr) +{ + return 0; +} + +//============================================================================= + +int WINS_CheckNewConnections (void) +{ + char buf[4096]; + + if (net_acceptsocket == -1) + return -1; + + if (precvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) > 0) + { + return net_acceptsocket; + } + return -1; +} + +//============================================================================= + +int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int addrlen = sizeof (struct qsockaddr); + int ret; + + ret = precvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); + if (ret == -1) + { + int errno = pWSAGetLastError(); + + if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) + return 0; + + } + return ret; +} + +//============================================================================= + +int WINS_MakeSocketBroadcastCapable (int socket) +{ + int i = 1; + + // make this socket broadcast capable + if (psetsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) + return -1; + net_broadcastsocket = socket; + + return 0; +} + +//============================================================================= + +int WINS_Broadcast (int socket, byte *buf, int len) +{ + int ret; + + if (socket != net_broadcastsocket) + { + if (net_broadcastsocket != 0) + Sys_Error("Attempted to use multiple broadcasts sockets\n"); + WINS_GetLocalAddress(); + ret = WINS_MakeSocketBroadcastCapable (socket); + if (ret == -1) + { + Con_Printf("Unable to make socket broadcast capable\n"); + return ret; + } + } + + return WINS_Write (socket, buf, len, &broadcastaddr); +} + +//============================================================================= + +int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int ret; + + ret = psendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); + if (ret == -1) + if (pWSAGetLastError() == WSAEWOULDBLOCK) + return 0; + + return ret; +} + +//============================================================================= + +char *WINS_AddrToString (struct qsockaddr *addr) +{ + static char buffer[22]; + int haddr; + + haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); + sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); + return buffer; +} + +//============================================================================= + +int WINS_StringToAddr (char *string, struct qsockaddr *addr) +{ + int ha1, ha2, ha3, ha4, hp; + int ipaddr; + + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp); + return 0; +} + +//============================================================================= + +int WINS_GetSocketAddr (int socket, struct qsockaddr *addr) +{ + int addrlen = sizeof(struct qsockaddr); + unsigned int a; + + Q_memset(addr, 0, sizeof(struct qsockaddr)); + pgetsockname(socket, (struct sockaddr *)addr, &addrlen); + a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + if (a == 0 || a == inet_addr("127.0.0.1")) + ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; + + return 0; +} + +//============================================================================= + +int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + struct hostent *hostentry; + + hostentry = pgethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); + if (hostentry) + { + Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); + return 0; + } + + Q_strcpy (name, WINS_AddrToString (addr)); + return 0; +} + +//============================================================================= + +int WINS_GetAddrFromName(char *name, struct qsockaddr *addr) +{ + struct hostent *hostentry; + + if (name[0] >= '0' && name[0] <= '9') + return PartialIPAddress (name, addr); + + hostentry = pgethostbyname (name); + if (!hostentry) + return -1; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport); + ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; + + return 0; +} + +//============================================================================= + +int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) + return 1; + + return 0; +} + +//============================================================================= + +int WINS_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_in *)addr)->sin_port); +} + + +int WINS_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port); + return 0; +} + +//============================================================================= diff --git a/WinQuake/net_wins.h b/WinQuake/net_wins.h index 756ce64..1f77d01 100644 --- a/WinQuake/net_wins.h +++ b/WinQuake/net_wins.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_wins.h - -int WINS_Init (void); -void WINS_Shutdown (void); -void WINS_Listen (qboolean state); -int WINS_OpenSocket (int port); -int WINS_CloseSocket (int socket); -int WINS_Connect (int socket, struct qsockaddr *addr); -int WINS_CheckNewConnections (void); -int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int WINS_Broadcast (int socket, byte *buf, int len); -char *WINS_AddrToString (struct qsockaddr *addr); -int WINS_StringToAddr (char *string, struct qsockaddr *addr); -int WINS_GetSocketAddr (int socket, struct qsockaddr *addr); -int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name); -int WINS_GetAddrFromName (char *name, struct qsockaddr *addr); -int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int WINS_GetSocketPort (struct qsockaddr *addr); -int WINS_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_wins.h + +int WINS_Init (void); +void WINS_Shutdown (void); +void WINS_Listen (qboolean state); +int WINS_OpenSocket (int port); +int WINS_CloseSocket (int socket); +int WINS_Connect (int socket, struct qsockaddr *addr); +int WINS_CheckNewConnections (void); +int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int WINS_Broadcast (int socket, byte *buf, int len); +char *WINS_AddrToString (struct qsockaddr *addr); +int WINS_StringToAddr (char *string, struct qsockaddr *addr); +int WINS_GetSocketAddr (int socket, struct qsockaddr *addr); +int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name); +int WINS_GetAddrFromName (char *name, struct qsockaddr *addr); +int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int WINS_GetSocketPort (struct qsockaddr *addr); +int WINS_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/net_wipx.c b/WinQuake/net_wipx.c index a2ac624..6438a6d 100644 --- a/WinQuake/net_wipx.c +++ b/WinQuake/net_wipx.c @@ -1,432 +1,432 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_wipx.c - -#include "quakedef.h" -#include "winquake.h" -#include -#include "net_wipx.h" - -extern cvar_t hostname; - -#define MAXHOSTNAMELEN 256 - -static int net_acceptsocket = -1; // socket for fielding new connections -static int net_controlsocket; -static struct qsockaddr broadcastaddr; - -extern qboolean winsock_initialized; -extern WSADATA winsockdata; - -#define IPXSOCKETS 18 -static int ipxsocket[IPXSOCKETS]; -static int sequence[IPXSOCKETS]; - -//============================================================================= - -int WIPX_Init (void) -{ - int i; - char buff[MAXHOSTNAMELEN]; - struct qsockaddr addr; - char *p; - int r; - WORD wVersionRequested; - - if (COM_CheckParm ("-noipx")) - return -1; - -// make sure LoadLibrary has happened successfully - if (!winsock_lib_initialized) - return -1; - - if (winsock_initialized == 0) - { - wVersionRequested = MAKEWORD(1, 1); - - r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); - - if (r) - { - Con_Printf ("Winsock initialization failed.\n"); - return -1; - } - } - winsock_initialized++; - - for (i = 0; i < IPXSOCKETS; i++) - ipxsocket[i] = 0; - - // determine my name & address - if (pgethostname(buff, MAXHOSTNAMELEN) == 0) - { - // if the quake hostname isn't set, set it to the machine name - if (Q_strcmp(hostname.string, "UNNAMED") == 0) - { - // see if it's a text IP address (well, close enough) - for (p = buff; *p; p++) - if ((*p < '0' || *p > '9') && *p != '.') - break; - - // if it is a real name, strip off the domain; we only want the host - if (*p) - { - for (i = 0; i < 15; i++) - if (buff[i] == '.') - break; - buff[i] = 0; - } - Cvar_Set ("hostname", buff); - } - } - - if ((net_controlsocket = WIPX_OpenSocket (0)) == -1) - { - Con_Printf("WIPX_Init: Unable to open control socket\n"); - if (--winsock_initialized == 0) - pWSACleanup (); - return -1; - } - - ((struct sockaddr_ipx *)&broadcastaddr)->sa_family = AF_IPX; - memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_netnum, 0, 4); - memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_nodenum, 0xff, 6); - ((struct sockaddr_ipx *)&broadcastaddr)->sa_socket = htons((unsigned short)net_hostport); - - WIPX_GetSocketAddr (net_controlsocket, &addr); - Q_strcpy(my_ipx_address, WIPX_AddrToString (&addr)); - p = Q_strrchr (my_ipx_address, ':'); - if (p) - *p = 0; - - Con_Printf("Winsock IPX Initialized\n"); - ipxAvailable = true; - - return net_controlsocket; -} - -//============================================================================= - -void WIPX_Shutdown (void) -{ - WIPX_Listen (false); - WIPX_CloseSocket (net_controlsocket); - if (--winsock_initialized == 0) - pWSACleanup (); -} - -//============================================================================= - -void WIPX_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1) - Sys_Error ("WIPX_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - WIPX_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - -//============================================================================= - -int WIPX_OpenSocket (int port) -{ - int handle; - int newsocket; - struct sockaddr_ipx address; - u_long _true = 1; - - for (handle = 0; handle < IPXSOCKETS; handle++) - if (ipxsocket[handle] == 0) - break; - if (handle == IPXSOCKETS) - return -1; - - if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET) - return -1; - - if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) - goto ErrorReturn; - - if (psetsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) < 0) - goto ErrorReturn; - - address.sa_family = AF_IPX; - memset(address.sa_netnum, 0, 4); - memset(address.sa_nodenum, 0, 6);; - address.sa_socket = htons((unsigned short)port); - if( bind (newsocket, (void *)&address, sizeof(address)) == 0) - { - ipxsocket[handle] = newsocket; - sequence[handle] = 0; - return handle; - } - - Sys_Error ("Winsock IPX bind failed\n"); -ErrorReturn: - pclosesocket (newsocket); - return -1; -} - -//============================================================================= - -int WIPX_CloseSocket (int handle) -{ - int socket = ipxsocket[handle]; - int ret; - - ret = pclosesocket (socket); - ipxsocket[handle] = 0; - return ret; -} - - -//============================================================================= - -int WIPX_Connect (int handle, struct qsockaddr *addr) -{ - return 0; -} - -//============================================================================= - -int WIPX_CheckNewConnections (void) -{ - unsigned long available; - - if (net_acceptsocket == -1) - return -1; - - if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1) - Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed\n"); - if (available) - return net_acceptsocket; - return -1; -} - -//============================================================================= - -static byte packetBuffer[NET_DATAGRAMSIZE + 4]; - -int WIPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) -{ - int addrlen = sizeof (struct qsockaddr); - int socket = ipxsocket[handle]; - int ret; - - ret = precvfrom (socket, packetBuffer, len+4, 0, (struct sockaddr *)addr, &addrlen); - if (ret == -1) - { - int errno = pWSAGetLastError(); - - if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) - return 0; - - } - - if (ret < 4) - return 0; - - // remove sequence number, it's only needed for DOS IPX - ret -= 4; - memcpy(buf, packetBuffer+4, ret); - - return ret; -} - -//============================================================================= - -int WIPX_Broadcast (int handle, byte *buf, int len) -{ - return WIPX_Write (handle, buf, len, &broadcastaddr); -} - -//============================================================================= - -int WIPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) -{ - int socket = ipxsocket[handle]; - int ret; - - // build packet with sequence number - *(int *)(&packetBuffer[0]) = sequence[handle]; - sequence[handle]++; - memcpy(&packetBuffer[4], buf, len); - len += 4; - - ret = psendto (socket, packetBuffer, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); - if (ret == -1) - if (pWSAGetLastError() == WSAEWOULDBLOCK) - return 0; - - return ret; -} - -//============================================================================= - -char *WIPX_AddrToString (struct qsockaddr *addr) -{ - static char buf[28]; - - sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", - ((struct sockaddr_ipx *)addr)->sa_netnum[0] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_netnum[1] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_netnum[2] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_netnum[3] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[0] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[1] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[2] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[3] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[4] & 0xff, - ((struct sockaddr_ipx *)addr)->sa_nodenum[5] & 0xff, - ntohs(((struct sockaddr_ipx *)addr)->sa_socket) - ); - return buf; -} - -//============================================================================= - -int WIPX_StringToAddr (char *string, struct qsockaddr *addr) -{ - int val; - char buf[3]; - - buf[2] = 0; - Q_memset(addr, 0, sizeof(struct qsockaddr)); - addr->sa_family = AF_IPX; - -#define DO(src,dest) \ - buf[0] = string[src]; \ - buf[1] = string[src + 1]; \ - if (sscanf (buf, "%x", &val) != 1) \ - return -1; \ - ((struct sockaddr_ipx *)addr)->dest = val - - DO(0, sa_netnum[0]); - DO(2, sa_netnum[1]); - DO(4, sa_netnum[2]); - DO(6, sa_netnum[3]); - DO(9, sa_nodenum[0]); - DO(11, sa_nodenum[1]); - DO(13, sa_nodenum[2]); - DO(15, sa_nodenum[3]); - DO(17, sa_nodenum[4]); - DO(19, sa_nodenum[5]); -#undef DO - - sscanf (&string[22], "%u", &val); - ((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)val); - - return 0; -} - -//============================================================================= - -int WIPX_GetSocketAddr (int handle, struct qsockaddr *addr) -{ - int socket = ipxsocket[handle]; - int addrlen = sizeof(struct qsockaddr); - unsigned int a; - - Q_memset(addr, 0, sizeof(struct qsockaddr)); - if(pgetsockname(socket, (struct sockaddr *)addr, &addrlen) != 0) - { - int errno = pWSAGetLastError(); - } - - return 0; -} - -//============================================================================= - -int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name) -{ - Q_strcpy(name, WIPX_AddrToString(addr)); - return 0; -} - -//============================================================================= - -int WIPX_GetAddrFromName(char *name, struct qsockaddr *addr) -{ - int n; - char buf[32]; - - n = Q_strlen(name); - - if (n == 12) - { - sprintf(buf, "00000000:%s:%u", name, net_hostport); - return WIPX_StringToAddr (buf, addr); - } - if (n == 21) - { - sprintf(buf, "%s:%u", name, net_hostport); - return WIPX_StringToAddr (buf, addr); - } - if (n > 21 && n <= 27) - return WIPX_StringToAddr (name, addr); - - return -1; -} - -//============================================================================= - -int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if (*((struct sockaddr_ipx *)addr1)->sa_netnum && *((struct sockaddr_ipx *)addr2)->sa_netnum) - if (memcmp(((struct sockaddr_ipx *)addr1)->sa_netnum, ((struct sockaddr_ipx *)addr2)->sa_netnum, 4) != 0) - return -1; - if (memcmp(((struct sockaddr_ipx *)addr1)->sa_nodenum, ((struct sockaddr_ipx *)addr2)->sa_nodenum, 6) != 0) - return -1; - - if (((struct sockaddr_ipx *)addr1)->sa_socket != ((struct sockaddr_ipx *)addr2)->sa_socket) - return 1; - - return 0; -} - -//============================================================================= - -int WIPX_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_ipx *)addr)->sa_socket); -} - - -int WIPX_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)port); - return 0; -} - -//============================================================================= +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_wipx.c + +#include "quakedef.h" +#include "winquake.h" +#include +#include "net_wipx.h" + +extern cvar_t hostname; + +#define MAXHOSTNAMELEN 256 + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket; +static struct qsockaddr broadcastaddr; + +extern qboolean winsock_initialized; +extern WSADATA winsockdata; + +#define IPXSOCKETS 18 +static int ipxsocket[IPXSOCKETS]; +static int sequence[IPXSOCKETS]; + +//============================================================================= + +int WIPX_Init (void) +{ + int i; + char buff[MAXHOSTNAMELEN]; + struct qsockaddr addr; + char *p; + int r; + WORD wVersionRequested; + + if (COM_CheckParm ("-noipx")) + return -1; + +// make sure LoadLibrary has happened successfully + if (!winsock_lib_initialized) + return -1; + + if (winsock_initialized == 0) + { + wVersionRequested = MAKEWORD(1, 1); + + r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); + + if (r) + { + Con_Printf ("Winsock initialization failed.\n"); + return -1; + } + } + winsock_initialized++; + + for (i = 0; i < IPXSOCKETS; i++) + ipxsocket[i] = 0; + + // determine my name & address + if (pgethostname(buff, MAXHOSTNAMELEN) == 0) + { + // if the quake hostname isn't set, set it to the machine name + if (Q_strcmp(hostname.string, "UNNAMED") == 0) + { + // see if it's a text IP address (well, close enough) + for (p = buff; *p; p++) + if ((*p < '0' || *p > '9') && *p != '.') + break; + + // if it is a real name, strip off the domain; we only want the host + if (*p) + { + for (i = 0; i < 15; i++) + if (buff[i] == '.') + break; + buff[i] = 0; + } + Cvar_Set ("hostname", buff); + } + } + + if ((net_controlsocket = WIPX_OpenSocket (0)) == -1) + { + Con_Printf("WIPX_Init: Unable to open control socket\n"); + if (--winsock_initialized == 0) + pWSACleanup (); + return -1; + } + + ((struct sockaddr_ipx *)&broadcastaddr)->sa_family = AF_IPX; + memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_netnum, 0, 4); + memset(((struct sockaddr_ipx *)&broadcastaddr)->sa_nodenum, 0xff, 6); + ((struct sockaddr_ipx *)&broadcastaddr)->sa_socket = htons((unsigned short)net_hostport); + + WIPX_GetSocketAddr (net_controlsocket, &addr); + Q_strcpy(my_ipx_address, WIPX_AddrToString (&addr)); + p = Q_strrchr (my_ipx_address, ':'); + if (p) + *p = 0; + + Con_Printf("Winsock IPX Initialized\n"); + ipxAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void WIPX_Shutdown (void) +{ + WIPX_Listen (false); + WIPX_CloseSocket (net_controlsocket); + if (--winsock_initialized == 0) + pWSACleanup (); +} + +//============================================================================= + +void WIPX_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1) + Sys_Error ("WIPX_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + WIPX_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int WIPX_OpenSocket (int port) +{ + int handle; + int newsocket; + struct sockaddr_ipx address; + u_long _true = 1; + + for (handle = 0; handle < IPXSOCKETS; handle++) + if (ipxsocket[handle] == 0) + break; + if (handle == IPXSOCKETS) + return -1; + + if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET) + return -1; + + if (pioctlsocket (newsocket, FIONBIO, &_true) == -1) + goto ErrorReturn; + + if (psetsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) < 0) + goto ErrorReturn; + + address.sa_family = AF_IPX; + memset(address.sa_netnum, 0, 4); + memset(address.sa_nodenum, 0, 6);; + address.sa_socket = htons((unsigned short)port); + if( bind (newsocket, (void *)&address, sizeof(address)) == 0) + { + ipxsocket[handle] = newsocket; + sequence[handle] = 0; + return handle; + } + + Sys_Error ("Winsock IPX bind failed\n"); +ErrorReturn: + pclosesocket (newsocket); + return -1; +} + +//============================================================================= + +int WIPX_CloseSocket (int handle) +{ + int socket = ipxsocket[handle]; + int ret; + + ret = pclosesocket (socket); + ipxsocket[handle] = 0; + return ret; +} + + +//============================================================================= + +int WIPX_Connect (int handle, struct qsockaddr *addr) +{ + return 0; +} + +//============================================================================= + +int WIPX_CheckNewConnections (void) +{ + unsigned long available; + + if (net_acceptsocket == -1) + return -1; + + if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1) + Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed\n"); + if (available) + return net_acceptsocket; + return -1; +} + +//============================================================================= + +static byte packetBuffer[NET_DATAGRAMSIZE + 4]; + +int WIPX_Read (int handle, byte *buf, int len, struct qsockaddr *addr) +{ + int addrlen = sizeof (struct qsockaddr); + int socket = ipxsocket[handle]; + int ret; + + ret = precvfrom (socket, packetBuffer, len+4, 0, (struct sockaddr *)addr, &addrlen); + if (ret == -1) + { + int errno = pWSAGetLastError(); + + if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED) + return 0; + + } + + if (ret < 4) + return 0; + + // remove sequence number, it's only needed for DOS IPX + ret -= 4; + memcpy(buf, packetBuffer+4, ret); + + return ret; +} + +//============================================================================= + +int WIPX_Broadcast (int handle, byte *buf, int len) +{ + return WIPX_Write (handle, buf, len, &broadcastaddr); +} + +//============================================================================= + +int WIPX_Write (int handle, byte *buf, int len, struct qsockaddr *addr) +{ + int socket = ipxsocket[handle]; + int ret; + + // build packet with sequence number + *(int *)(&packetBuffer[0]) = sequence[handle]; + sequence[handle]++; + memcpy(&packetBuffer[4], buf, len); + len += 4; + + ret = psendto (socket, packetBuffer, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); + if (ret == -1) + if (pWSAGetLastError() == WSAEWOULDBLOCK) + return 0; + + return ret; +} + +//============================================================================= + +char *WIPX_AddrToString (struct qsockaddr *addr) +{ + static char buf[28]; + + sprintf(buf, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u", + ((struct sockaddr_ipx *)addr)->sa_netnum[0] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_netnum[1] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_netnum[2] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_netnum[3] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[0] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[1] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[2] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[3] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[4] & 0xff, + ((struct sockaddr_ipx *)addr)->sa_nodenum[5] & 0xff, + ntohs(((struct sockaddr_ipx *)addr)->sa_socket) + ); + return buf; +} + +//============================================================================= + +int WIPX_StringToAddr (char *string, struct qsockaddr *addr) +{ + int val; + char buf[3]; + + buf[2] = 0; + Q_memset(addr, 0, sizeof(struct qsockaddr)); + addr->sa_family = AF_IPX; + +#define DO(src,dest) \ + buf[0] = string[src]; \ + buf[1] = string[src + 1]; \ + if (sscanf (buf, "%x", &val) != 1) \ + return -1; \ + ((struct sockaddr_ipx *)addr)->dest = val + + DO(0, sa_netnum[0]); + DO(2, sa_netnum[1]); + DO(4, sa_netnum[2]); + DO(6, sa_netnum[3]); + DO(9, sa_nodenum[0]); + DO(11, sa_nodenum[1]); + DO(13, sa_nodenum[2]); + DO(15, sa_nodenum[3]); + DO(17, sa_nodenum[4]); + DO(19, sa_nodenum[5]); +#undef DO + + sscanf (&string[22], "%u", &val); + ((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)val); + + return 0; +} + +//============================================================================= + +int WIPX_GetSocketAddr (int handle, struct qsockaddr *addr) +{ + int socket = ipxsocket[handle]; + int addrlen = sizeof(struct qsockaddr); + unsigned int a; + + Q_memset(addr, 0, sizeof(struct qsockaddr)); + if(pgetsockname(socket, (struct sockaddr *)addr, &addrlen) != 0) + { + int errno = pWSAGetLastError(); + } + + return 0; +} + +//============================================================================= + +int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ + Q_strcpy(name, WIPX_AddrToString(addr)); + return 0; +} + +//============================================================================= + +int WIPX_GetAddrFromName(char *name, struct qsockaddr *addr) +{ + int n; + char buf[32]; + + n = Q_strlen(name); + + if (n == 12) + { + sprintf(buf, "00000000:%s:%u", name, net_hostport); + return WIPX_StringToAddr (buf, addr); + } + if (n == 21) + { + sprintf(buf, "%s:%u", name, net_hostport); + return WIPX_StringToAddr (buf, addr); + } + if (n > 21 && n <= 27) + return WIPX_StringToAddr (name, addr); + + return -1; +} + +//============================================================================= + +int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (*((struct sockaddr_ipx *)addr1)->sa_netnum && *((struct sockaddr_ipx *)addr2)->sa_netnum) + if (memcmp(((struct sockaddr_ipx *)addr1)->sa_netnum, ((struct sockaddr_ipx *)addr2)->sa_netnum, 4) != 0) + return -1; + if (memcmp(((struct sockaddr_ipx *)addr1)->sa_nodenum, ((struct sockaddr_ipx *)addr2)->sa_nodenum, 6) != 0) + return -1; + + if (((struct sockaddr_ipx *)addr1)->sa_socket != ((struct sockaddr_ipx *)addr2)->sa_socket) + return 1; + + return 0; +} + +//============================================================================= + +int WIPX_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_ipx *)addr)->sa_socket); +} + + +int WIPX_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_ipx *)addr)->sa_socket = htons((unsigned short)port); + return 0; +} + +//============================================================================= diff --git a/WinQuake/net_wipx.h b/WinQuake/net_wipx.h index ed82dc1..b8adf41 100644 --- a/WinQuake/net_wipx.h +++ b/WinQuake/net_wipx.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_wipx.h - -int WIPX_Init (void); -void WIPX_Shutdown (void); -void WIPX_Listen (qboolean state); -int WIPX_OpenSocket (int port); -int WIPX_CloseSocket (int socket); -int WIPX_Connect (int socket, struct qsockaddr *addr); -int WIPX_CheckNewConnections (void); -int WIPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr); -int WIPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr); -int WIPX_Broadcast (int socket, byte *buf, int len); -char *WIPX_AddrToString (struct qsockaddr *addr); -int WIPX_StringToAddr (char *string, struct qsockaddr *addr); -int WIPX_GetSocketAddr (int socket, struct qsockaddr *addr); -int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name); -int WIPX_GetAddrFromName (char *name, struct qsockaddr *addr); -int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); -int WIPX_GetSocketPort (struct qsockaddr *addr); -int WIPX_SetSocketPort (struct qsockaddr *addr, int port); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_wipx.h + +int WIPX_Init (void); +void WIPX_Shutdown (void); +void WIPX_Listen (qboolean state); +int WIPX_OpenSocket (int port); +int WIPX_CloseSocket (int socket); +int WIPX_Connect (int socket, struct qsockaddr *addr); +int WIPX_CheckNewConnections (void); +int WIPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int WIPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int WIPX_Broadcast (int socket, byte *buf, int len); +char *WIPX_AddrToString (struct qsockaddr *addr); +int WIPX_StringToAddr (char *string, struct qsockaddr *addr); +int WIPX_GetSocketAddr (int socket, struct qsockaddr *addr); +int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name); +int WIPX_GetAddrFromName (char *name, struct qsockaddr *addr); +int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int WIPX_GetSocketPort (struct qsockaddr *addr); +int WIPX_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/WinQuake/nonintel.c b/WinQuake/nonintel.c index 9e59039..66a9d10 100644 --- a/WinQuake/nonintel.c +++ b/WinQuake/nonintel.c @@ -1,64 +1,64 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// nonintel.c: code for non-Intel processors only -// - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - -#if !id386 - -/* -================ -R_Surf8Patch -================ -*/ -void R_Surf8Patch () -{ - // we only patch code on Intel -} - - -/* -================ -R_Surf16Patch -================ -*/ -void R_Surf16Patch () -{ - // we only patch code on Intel -} - - -/* -================ -R_SurfacePatch -================ -*/ -void R_SurfacePatch (void) -{ - // we only patch code on Intel -} - - -#endif // !id386 - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// nonintel.c: code for non-Intel processors only +// + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" + +#if !id386 + +/* +================ +R_Surf8Patch +================ +*/ +void R_Surf8Patch () +{ + // we only patch code on Intel +} + + +/* +================ +R_Surf16Patch +================ +*/ +void R_Surf16Patch () +{ + // we only patch code on Intel +} + + +/* +================ +R_SurfacePatch +================ +*/ +void R_SurfacePatch (void) +{ + // we only patch code on Intel +} + + +#endif // !id386 + diff --git a/WinQuake/pr_cmds.c b/WinQuake/pr_cmds.c index 3593bb9..a80cd46 100644 --- a/WinQuake/pr_cmds.c +++ b/WinQuake/pr_cmds.c @@ -1,1934 +1,1934 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - -#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) - -/* -=============================================================================== - - BUILT-IN FUNCTIONS - -=============================================================================== -*/ - -char *PF_VarString (int first) -{ - int i; - static char out[256]; - - out[0] = 0; - for (i=first ; is_name,s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); - - Host_Error ("Program error"); -} - -/* -================= -PF_objerror - -Dumps out self, then an error message. The program is aborted and self is -removed, but the level can continue. - -objerror(value) -================= -*/ -void PF_objerror (void) -{ - char *s; - edict_t *ed; - - s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n" - ,pr_strings + pr_xfunction->s_name,s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); - ED_Free (ed); - - Host_Error ("Program error"); -} - - - -/* -============== -PF_makevectors - -Writes new values for v_forward, v_up, and v_right based on angles -makevectors(vector) -============== -*/ -void PF_makevectors (void) -{ - AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); -} - -/* -================= -PF_setorigin - -This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported. - -setorigin (entity, origin) -================= -*/ -void PF_setorigin (void) -{ - edict_t *e; - float *org; - - e = G_EDICT(OFS_PARM0); - org = G_VECTOR(OFS_PARM1); - VectorCopy (org, e->v.origin); - SV_LinkEdict (e, false); -} - - -void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) -{ - float *angles; - vec3_t rmin, rmax; - float bounds[2][3]; - float xvector[2], yvector[2]; - float a; - vec3_t base, transformed; - int i, j, k, l; - - for (i=0 ; i<3 ; i++) - if (min[i] > max[i]) - PR_RunError ("backwards mins/maxs"); - - rotate = false; // FIXME: implement rotation properly again - - if (!rotate) - { - VectorCopy (min, rmin); - VectorCopy (max, rmax); - } - else - { - // find min / max for rotations - angles = e->v.angles; - - a = angles[1]/180 * M_PI; - - xvector[0] = cos(a); - xvector[1] = sin(a); - yvector[0] = -sin(a); - yvector[1] = cos(a); - - VectorCopy (min, bounds[0]); - VectorCopy (max, bounds[1]); - - rmin[0] = rmin[1] = rmin[2] = 9999; - rmax[0] = rmax[1] = rmax[2] = -9999; - - for (i=0 ; i<= 1 ; i++) - { - base[0] = bounds[i][0]; - for (j=0 ; j<= 1 ; j++) - { - base[1] = bounds[j][1]; - for (k=0 ; k<= 1 ; k++) - { - base[2] = bounds[k][2]; - - // transform the point - transformed[0] = xvector[0]*base[0] + yvector[0]*base[1]; - transformed[1] = xvector[1]*base[0] + yvector[1]*base[1]; - transformed[2] = base[2]; - - for (l=0 ; l<3 ; l++) - { - if (transformed[l] < rmin[l]) - rmin[l] = transformed[l]; - if (transformed[l] > rmax[l]) - rmax[l] = transformed[l]; - } - } - } - } - } - -// set derived values - VectorCopy (rmin, e->v.mins); - VectorCopy (rmax, e->v.maxs); - VectorSubtract (max, min, e->v.size); - - SV_LinkEdict (e, false); -} - -/* -================= -PF_setsize - -the size box is rotated by the current angle - -setsize (entity, minvector, maxvector) -================= -*/ -void PF_setsize (void) -{ - edict_t *e; - float *min, *max; - - e = G_EDICT(OFS_PARM0); - min = G_VECTOR(OFS_PARM1); - max = G_VECTOR(OFS_PARM2); - SetMinMaxSize (e, min, max, false); -} - - -/* -================= -PF_setmodel - -setmodel(entity, model) -================= -*/ -void PF_setmodel (void) -{ - edict_t *e; - char *m, **check; - model_t *mod; - int i; - - e = G_EDICT(OFS_PARM0); - m = G_STRING(OFS_PARM1); - -// check to see if model was properly precached - for (i=0, check = sv.model_precache ; *check ; i++, check++) - if (!strcmp(*check, m)) - break; - - if (!*check) - PR_RunError ("no precache: %s\n", m); - - - e->v.model = m - pr_strings; - e->v.modelindex = i; //SV_ModelIndex (m); - - mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true); - - if (mod) - SetMinMaxSize (e, mod->mins, mod->maxs, true); - else - SetMinMaxSize (e, vec3_origin, vec3_origin, true); -} - -/* -================= -PF_bprint - -broadcast print to everyone on server - -bprint(value) -================= -*/ -void PF_bprint (void) -{ - char *s; - - s = PF_VarString(0); - SV_BroadcastPrintf ("%s", s); -} - -/* -================= -PF_sprint - -single print to a specific client - -sprint(clientent, value) -================= -*/ -void PF_sprint (void) -{ - char *s; - client_t *client; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) - { - Con_Printf ("tried to sprint to a non-client\n"); - return; - } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_print); - MSG_WriteString (&client->message, s ); -} - - -/* -================= -PF_centerprint - -single print to a specific client - -centerprint(clientent, value) -================= -*/ -void PF_centerprint (void) -{ - char *s; - client_t *client; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) - { - Con_Printf ("tried to sprint to a non-client\n"); - return; - } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_centerprint); - MSG_WriteString (&client->message, s ); -} - - -/* -================= -PF_normalize - -vector normalize(vector) -================= -*/ -void PF_normalize (void) -{ - float *value1; - vec3_t newvalue; - float new; - - value1 = G_VECTOR(OFS_PARM0); - - new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; - new = sqrt(new); - - if (new == 0) - newvalue[0] = newvalue[1] = newvalue[2] = 0; - else - { - new = 1/new; - newvalue[0] = value1[0] * new; - newvalue[1] = value1[1] * new; - newvalue[2] = value1[2] * new; - } - - VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); -} - -/* -================= -PF_vlen - -scalar vlen(vector) -================= -*/ -void PF_vlen (void) -{ - float *value1; - float new; - - value1 = G_VECTOR(OFS_PARM0); - - new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; - new = sqrt(new); - - G_FLOAT(OFS_RETURN) = new; -} - -/* -================= -PF_vectoyaw - -float vectoyaw(vector) -================= -*/ -void PF_vectoyaw (void) -{ - float *value1; - float yaw; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - yaw = 0; - else - { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - } - - G_FLOAT(OFS_RETURN) = yaw; -} - - -/* -================= -PF_vectoangles - -vector vectoangles(vector) -================= -*/ -void PF_vectoangles (void) -{ - float *value1; - float forward; - float yaw, pitch; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - { - yaw = 0; - if (value1[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); - pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - G_FLOAT(OFS_RETURN+0) = pitch; - G_FLOAT(OFS_RETURN+1) = yaw; - G_FLOAT(OFS_RETURN+2) = 0; -} - -/* -================= -PF_Random - -Returns a number from 0<= num < 1 - -random() -================= -*/ -void PF_random (void) -{ - float num; - - num = (rand ()&0x7fff) / ((float)0x7fff); - - G_FLOAT(OFS_RETURN) = num; -} - -/* -================= -PF_particle - -particle(origin, color, count) -================= -*/ -void PF_particle (void) -{ - float *org, *dir; - float color; - float count; - - org = G_VECTOR(OFS_PARM0); - dir = G_VECTOR(OFS_PARM1); - color = G_FLOAT(OFS_PARM2); - count = G_FLOAT(OFS_PARM3); - SV_StartParticle (org, dir, color, count); -} - - -/* -================= -PF_ambientsound - -================= -*/ -void PF_ambientsound (void) -{ - char **check; - char *samp; - float *pos; - float vol, attenuation; - int i, soundnum; - - pos = G_VECTOR (OFS_PARM0); - samp = G_STRING(OFS_PARM1); - vol = G_FLOAT(OFS_PARM2); - attenuation = G_FLOAT(OFS_PARM3); - -// check to see if samp was properly precached - for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++) - if (!strcmp(*check,samp)) - break; - - if (!*check) - { - Con_Printf ("no precache: %s\n", samp); - return; - } - -// add an svc_spawnambient command to the level signon packet - - MSG_WriteByte (&sv.signon,svc_spawnstaticsound); - for (i=0 ; i<3 ; i++) - MSG_WriteCoord(&sv.signon, pos[i]); - - MSG_WriteByte (&sv.signon, soundnum); - - MSG_WriteByte (&sv.signon, vol*255); - MSG_WriteByte (&sv.signon, attenuation*64); - -} - -/* -================= -PF_sound - -Each entity can have eight independant sound sources, like voice, -weapon, feet, etc. - -Channel 0 is an auto-allocate channel, the others override anything -allready running on that entity/channel pair. - -An attenuation of 0 will play full volume everywhere in the level. -Larger attenuations will drop off. - -================= -*/ -void PF_sound (void) -{ - char *sample; - int channel; - edict_t *entity; - int volume; - float attenuation; - - entity = G_EDICT(OFS_PARM0); - channel = G_FLOAT(OFS_PARM1); - sample = G_STRING(OFS_PARM2); - volume = G_FLOAT(OFS_PARM3) * 255; - attenuation = G_FLOAT(OFS_PARM4); - - if (volume < 0 || volume > 255) - Sys_Error ("SV_StartSound: volume = %i", volume); - - if (attenuation < 0 || attenuation > 4) - Sys_Error ("SV_StartSound: attenuation = %f", attenuation); - - if (channel < 0 || channel > 7) - Sys_Error ("SV_StartSound: channel = %i", channel); - - SV_StartSound (entity, channel, sample, volume, attenuation); -} - -/* -================= -PF_break - -break() -================= -*/ -void PF_break (void) -{ -Con_Printf ("break statement\n"); -*(int *)-4 = 0; // dump to debugger -// PR_RunError ("break statement"); -} - -/* -================= -PF_traceline - -Used for use tracing and shot targeting -Traces are blocked by bbox and exact bsp entityes, and also slide box entities -if the tryents flag is set. - -traceline (vector1, vector2, tryents) -================= -*/ -void PF_traceline (void) -{ - float *v1, *v2; - trace_t trace; - int nomonsters; - edict_t *ent; - - v1 = G_VECTOR(OFS_PARM0); - v2 = G_VECTOR(OFS_PARM1); - nomonsters = G_FLOAT(OFS_PARM2); - ent = G_EDICT(OFS_PARM3); - - trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); - - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; - if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); - else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); -} - - -#ifdef QUAKE2 -extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); - -void PF_TraceToss (void) -{ - trace_t trace; - edict_t *ent; - edict_t *ignore; - - ent = G_EDICT(OFS_PARM0); - ignore = G_EDICT(OFS_PARM1); - - trace = SV_Trace_Toss (ent, ignore); - - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; - if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); - else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); -} -#endif - - -/* -================= -PF_checkpos - -Returns true if the given entity can move to the given position from it's -current position by walking or rolling. -FIXME: make work... -scalar checkpos (entity, vector) -================= -*/ -void PF_checkpos (void) -{ -} - -//============================================================================ - -byte checkpvs[MAX_MAP_LEAFS/8]; - -int PF_newcheckclient (int check) -{ - int i; - byte *pvs; - edict_t *ent; - mleaf_t *leaf; - vec3_t org; - -// cycle to the next one - - if (check < 1) - check = 1; - if (check > svs.maxclients) - check = svs.maxclients; - - if (check == svs.maxclients) - i = 1; - else - i = check + 1; - - for ( ; ; i++) - { - if (i == svs.maxclients+1) - i = 1; - - ent = EDICT_NUM(i); - - if (i == check) - break; // didn't find anything else - - if (ent->free) - continue; - if (ent->v.health <= 0) - continue; - if ((int)ent->v.flags & FL_NOTARGET) - continue; - - // anything that is a client, or has a client as an enemy - break; - } - -// get the PVS for the entity - VectorAdd (ent->v.origin, ent->v.view_ofs, org); - leaf = Mod_PointInLeaf (org, sv.worldmodel); - pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 ); - - return i; -} - -/* -================= -PF_checkclient - -Returns a client (or object that has a client enemy) that would be a -valid target. - -If there are more than one valid options, they are cycled each frame - -If (self.origin + self.viewofs) is not in the PVS of the current target, -it is not returned at all. - -name checkclient () -================= -*/ -#define MAX_CHECK 16 -int c_invis, c_notvis; -void PF_checkclient (void) -{ - edict_t *ent, *self; - mleaf_t *leaf; - int l; - vec3_t view; - -// find a new check if on a new frame - if (sv.time - sv.lastchecktime >= 0.1) - { - sv.lastcheck = PF_newcheckclient (sv.lastcheck); - sv.lastchecktime = sv.time; - } - -// return check if it might be visible - ent = EDICT_NUM(sv.lastcheck); - if (ent->free || ent->v.health <= 0) - { - RETURN_EDICT(sv.edicts); - return; - } - -// if current entity can't possibly see the check entity, return 0 - self = PROG_TO_EDICT(pr_global_struct->self); - VectorAdd (self->v.origin, self->v.view_ofs, view); - leaf = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) - { -c_notvis++; - RETURN_EDICT(sv.edicts); - return; - } - -// might be able to see it -c_invis++; - RETURN_EDICT(ent); -} - -//============================================================================ - - -/* -================= -PF_stuffcmd - -Sends text over to the client's execution buffer - -stuffcmd (clientent, value) -================= -*/ -void PF_stuffcmd (void) -{ - int entnum; - char *str; - client_t *old; - - entnum = G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("Parm 0 not a client"); - str = G_STRING(OFS_PARM1); - - old = host_client; - host_client = &svs.clients[entnum-1]; - Host_ClientCommands ("%s", str); - host_client = old; -} - -/* -================= -PF_localcmd - -Sends text over to the client's execution buffer - -localcmd (string) -================= -*/ -void PF_localcmd (void) -{ - char *str; - - str = G_STRING(OFS_PARM0); - Cbuf_AddText (str); -} - -/* -================= -PF_cvar - -float cvar (string) -================= -*/ -void PF_cvar (void) -{ - char *str; - - str = G_STRING(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); -} - -/* -================= -PF_cvar_set - -float cvar (string) -================= -*/ -void PF_cvar_set (void) -{ - char *var, *val; - - var = G_STRING(OFS_PARM0); - val = G_STRING(OFS_PARM1); - - Cvar_Set (var, val); -} - -/* -================= -PF_findradius - -Returns a chain of entities that have origins within a spherical area - -findradius (origin, radius) -================= -*/ -void PF_findradius (void) -{ - edict_t *ent, *chain; - float rad; - float *org; - vec3_t eorg; - int i, j; - - chain = (edict_t *)sv.edicts; - - org = G_VECTOR(OFS_PARM0); - rad = G_FLOAT(OFS_PARM1); - - ent = NEXT_EDICT(sv.edicts); - for (i=1 ; ifree) - continue; - if (ent->v.solid == SOLID_NOT) - continue; - for (j=0 ; j<3 ; j++) - eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5); - if (Length(eorg) > rad) - continue; - - ent->v.chain = EDICT_TO_PROG(chain); - chain = ent; - } - - RETURN_EDICT(chain); -} - - -/* -========= -PF_dprint -========= -*/ -void PF_dprint (void) -{ - Con_DPrintf ("%s",PF_VarString(0)); -} - -char pr_string_temp[128]; - -void PF_ftos (void) -{ - float v; - v = G_FLOAT(OFS_PARM0); - - if (v == (int)v) - sprintf (pr_string_temp, "%d",(int)v); - else - sprintf (pr_string_temp, "%5.1f",v); - G_INT(OFS_RETURN) = pr_string_temp - pr_strings; -} - -void PF_fabs (void) -{ - float v; - v = G_FLOAT(OFS_PARM0); - G_FLOAT(OFS_RETURN) = fabs(v); -} - -void PF_vtos (void) -{ - sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); - G_INT(OFS_RETURN) = pr_string_temp - pr_strings; -} - -#ifdef QUAKE2 -void PF_etos (void) -{ - sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0)); - G_INT(OFS_RETURN) = pr_string_temp - pr_strings; -} -#endif - -void PF_Spawn (void) -{ - edict_t *ed; - ed = ED_Alloc(); - RETURN_EDICT(ed); -} - -void PF_Remove (void) -{ - edict_t *ed; - - ed = G_EDICT(OFS_PARM0); - ED_Free (ed); -} - - -// entity (entity start, .string field, string match) find = #5; -void PF_Find (void) -#ifdef QUAKE2 -{ - int e; - int f; - char *s, *t; - edict_t *ed; - edict_t *first; - edict_t *second; - edict_t *last; - - first = second = last = (edict_t *)sv.edicts; - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_STRING(OFS_PARM2); - if (!s) - PR_RunError ("PF_Find: bad search string"); - - for (e++ ; e < sv.num_edicts ; e++) - { - ed = EDICT_NUM(e); - if (ed->free) - continue; - t = E_STRING(ed,f); - if (!t) - continue; - if (!strcmp(t,s)) - { - if (first == (edict_t *)sv.edicts) - first = ed; - else if (second == (edict_t *)sv.edicts) - second = ed; - ed->v.chain = EDICT_TO_PROG(last); - last = ed; - } - } - - if (first != last) - { - if (last != second) - first->v.chain = last->v.chain; - else - first->v.chain = EDICT_TO_PROG(last); - last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts); - if (second && second != last) - second->v.chain = EDICT_TO_PROG(last); - } - RETURN_EDICT(first); -} -#else -{ - int e; - int f; - char *s, *t; - edict_t *ed; - - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_STRING(OFS_PARM2); - if (!s) - PR_RunError ("PF_Find: bad search string"); - - for (e++ ; e < sv.num_edicts ; e++) - { - ed = EDICT_NUM(e); - if (ed->free) - continue; - t = E_STRING(ed,f); - if (!t) - continue; - if (!strcmp(t,s)) - { - RETURN_EDICT(ed); - return; - } - } - - RETURN_EDICT(sv.edicts); -} -#endif - -void PR_CheckEmptyString (char *s) -{ - if (s[0] <= ' ') - PR_RunError ("Bad string"); -} - -void PF_precache_file (void) -{ // precache_file is only used to copy files with qcc, it does nothing - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); -} - -void PF_precache_sound (void) -{ - char *s; - int i; - - if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); - - s = G_STRING(OFS_PARM0); - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); - - for (i=0 ; iself); - yaw = G_FLOAT(OFS_PARM0); - dist = G_FLOAT(OFS_PARM1); - - if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) - { - G_FLOAT(OFS_RETURN) = 0; - return; - } - - yaw = yaw*M_PI*2 / 360; - - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - -// save program state, because SV_movestep may call other progs - oldf = pr_xfunction; - oldself = pr_global_struct->self; - - G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); - - -// restore program state - pr_xfunction = oldf; - pr_global_struct->self = oldself; -} - -/* -=============== -PF_droptofloor - -void() droptofloor -=============== -*/ -void PF_droptofloor (void) -{ - edict_t *ent; - vec3_t end; - trace_t trace; - - ent = PROG_TO_EDICT(pr_global_struct->self); - - VectorCopy (ent->v.origin, end); - end[2] -= 256; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); - - if (trace.fraction == 1 || trace.allsolid) - G_FLOAT(OFS_RETURN) = 0; - else - { - VectorCopy (trace.endpos, ent->v.origin); - SV_LinkEdict (ent, false); - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - G_FLOAT(OFS_RETURN) = 1; - } -} - -/* -=============== -PF_lightstyle - -void(float style, string value) lightstyle -=============== -*/ -void PF_lightstyle (void) -{ - int style; - char *val; - client_t *client; - int j; - - style = G_FLOAT(OFS_PARM0); - val = G_STRING(OFS_PARM1); - -// change the string in sv - sv.lightstyles[style] = val; - -// send message to all clients on this server - if (sv.state != ss_active) - return; - - for (j=0, client = svs.clients ; jactive || client->spawned) - { - MSG_WriteChar (&client->message, svc_lightstyle); - MSG_WriteChar (&client->message,style); - MSG_WriteString (&client->message, val); - } -} - -void PF_rint (void) -{ - float f; - f = G_FLOAT(OFS_PARM0); - if (f > 0) - G_FLOAT(OFS_RETURN) = (int)(f + 0.5); - else - G_FLOAT(OFS_RETURN) = (int)(f - 0.5); -} -void PF_floor (void) -{ - G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); -} -void PF_ceil (void) -{ - G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); -} - - -/* -============= -PF_checkbottom -============= -*/ -void PF_checkbottom (void) -{ - edict_t *ent; - - ent = G_EDICT(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent); -} - -/* -============= -PF_pointcontents -============= -*/ -void PF_pointcontents (void) -{ - float *v; - - v = G_VECTOR(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = SV_PointContents (v); -} - -/* -============= -PF_nextent - -entity nextent(entity) -============= -*/ -void PF_nextent (void) -{ - int i; - edict_t *ent; - - i = G_EDICTNUM(OFS_PARM0); - while (1) - { - i++; - if (i == sv.num_edicts) - { - RETURN_EDICT(sv.edicts); - return; - } - ent = EDICT_NUM(i); - if (!ent->free) - { - RETURN_EDICT(ent); - return; - } - } -} - -/* -============= -PF_aim - -Pick a vector for the player to shoot along -vector aim(entity, missilespeed) -============= -*/ -cvar_t sv_aim = {"sv_aim", "0.93"}; -void PF_aim (void) -{ - edict_t *ent, *check, *bestent; - vec3_t start, dir, end, bestdir; - int i, j; - trace_t tr; - float dist, bestdist; - float speed; - - ent = G_EDICT(OFS_PARM0); - speed = G_FLOAT(OFS_PARM1); - - VectorCopy (ent->v.origin, start); - start[2] += 20; - -// try sending a trace straight - VectorCopy (pr_global_struct->v_forward, dir); - VectorMA (start, 2048, dir, end); - tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); - if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM - && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) ) - { - VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN)); - return; - } - - -// try all possible entities - VectorCopy (dir, bestdir); - bestdist = sv_aim.value; - bestent = NULL; - - check = NEXT_EDICT(sv.edicts); - for (i=1 ; iv.takedamage != DAMAGE_AIM) - continue; - if (check == ent) - continue; - if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team) - continue; // don't aim at teammate - for (j=0 ; j<3 ; j++) - end[j] = check->v.origin[j] - + 0.5*(check->v.mins[j] + check->v.maxs[j]); - VectorSubtract (end, start, dir); - VectorNormalize (dir); - dist = DotProduct (dir, pr_global_struct->v_forward); - if (dist < bestdist) - continue; // to far to turn - tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); - if (tr.ent == check) - { // can shoot at this one - bestdist = dist; - bestent = check; - } - } - - if (bestent) - { - VectorSubtract (bestent->v.origin, ent->v.origin, dir); - dist = DotProduct (dir, pr_global_struct->v_forward); - VectorScale (pr_global_struct->v_forward, dist, end); - end[2] = dir[2]; - VectorNormalize (end); - VectorCopy (end, G_VECTOR(OFS_RETURN)); - } - else - { - VectorCopy (bestdir, G_VECTOR(OFS_RETURN)); - } -} - -/* -============== -PF_changeyaw - -This was a major timewaster in progs, so it was converted to C -============== -*/ -void PF_changeyaw (void) -{ - edict_t *ent; - float ideal, current, move, speed; - - ent = PROG_TO_EDICT(pr_global_struct->self); - current = anglemod( ent->v.angles[1] ); - ideal = ent->v.ideal_yaw; - speed = ent->v.yaw_speed; - - if (current == ideal) - return; - move = ideal - current; - if (ideal > current) - { - if (move >= 180) - move = move - 360; - } - else - { - if (move <= -180) - move = move + 360; - } - if (move > 0) - { - if (move > speed) - move = speed; - } - else - { - if (move < -speed) - move = -speed; - } - - ent->v.angles[1] = anglemod (current + move); -} - -#ifdef QUAKE2 -/* -============== -PF_changepitch -============== -*/ -void PF_changepitch (void) -{ - edict_t *ent; - float ideal, current, move, speed; - - ent = G_EDICT(OFS_PARM0); - current = anglemod( ent->v.angles[0] ); - ideal = ent->v.idealpitch; - speed = ent->v.pitch_speed; - - if (current == ideal) - return; - move = ideal - current; - if (ideal > current) - { - if (move >= 180) - move = move - 360; - } - else - { - if (move <= -180) - move = move + 360; - } - if (move > 0) - { - if (move > speed) - move = speed; - } - else - { - if (move < -speed) - move = -speed; - } - - ent->v.angles[0] = anglemod (current + move); -} -#endif - -/* -=============================================================================== - -MESSAGE WRITING - -=============================================================================== -*/ - -#define MSG_BROADCAST 0 // unreliable to all -#define MSG_ONE 1 // reliable to one (msg_entity) -#define MSG_ALL 2 // reliable to all -#define MSG_INIT 3 // write to the init string - -sizebuf_t *WriteDest (void) -{ - int entnum; - int dest; - edict_t *ent; - - dest = G_FLOAT(OFS_PARM0); - switch (dest) - { - case MSG_BROADCAST: - return &sv.datagram; - - case MSG_ONE: - ent = PROG_TO_EDICT(pr_global_struct->msg_entity); - entnum = NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("WriteDest: not a client"); - return &svs.clients[entnum-1].message; - - case MSG_ALL: - return &sv.reliable_datagram; - - case MSG_INIT: - return &sv.signon; - - default: - PR_RunError ("WriteDest: bad destination"); - break; - } - - return NULL; -} - -void PF_WriteByte (void) -{ - MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteChar (void) -{ - MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteShort (void) -{ - MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteLong (void) -{ - MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteAngle (void) -{ - MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteCoord (void) -{ - MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -void PF_WriteString (void) -{ - MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1)); -} - - -void PF_WriteEntity (void) -{ - MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1)); -} - -//============================================================================= - -int SV_ModelIndex (char *name); - -void PF_makestatic (void) -{ - edict_t *ent; - int i; - - ent = G_EDICT(OFS_PARM0); - - MSG_WriteByte (&sv.signon,svc_spawnstatic); - - MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model)); - - MSG_WriteByte (&sv.signon, ent->v.frame); - MSG_WriteByte (&sv.signon, ent->v.colormap); - MSG_WriteByte (&sv.signon, ent->v.skin); - for (i=0 ; i<3 ; i++) - { - MSG_WriteCoord(&sv.signon, ent->v.origin[i]); - MSG_WriteAngle(&sv.signon, ent->v.angles[i]); - } - -// throw the entity away now - ED_Free (ent); -} - -//============================================================================= - -/* -============== -PF_setspawnparms -============== -*/ -void PF_setspawnparms (void) -{ - edict_t *ent; - int i; - client_t *client; - - ent = G_EDICT(OFS_PARM0); - i = NUM_FOR_EDICT(ent); - if (i < 1 || i > svs.maxclients) - PR_RunError ("Entity is not a client"); - - // copy spawn parms out of the client_t - client = svs.clients + (i-1); - - for (i=0 ; i< NUM_SPAWN_PARMS ; i++) - (&pr_global_struct->parm1)[i] = client->spawn_parms[i]; -} - -/* -============== -PF_changelevel -============== -*/ -void PF_changelevel (void) -{ -#ifdef QUAKE2 - char *s1, *s2; - - if (svs.changelevel_issued) - return; - svs.changelevel_issued = true; - - s1 = G_STRING(OFS_PARM0); - s2 = G_STRING(OFS_PARM1); - - if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE)) - Cbuf_AddText (va("changelevel %s %s\n",s1, s2)); - else - Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2)); -#else - char *s; - -// make sure we don't issue two changelevels - if (svs.changelevel_issued) - return; - svs.changelevel_issued = true; - - s = G_STRING(OFS_PARM0); - Cbuf_AddText (va("changelevel %s\n",s)); -#endif -} - - -#ifdef QUAKE2 - -#define CONTENT_WATER -3 -#define CONTENT_SLIME -4 -#define CONTENT_LAVA -5 - -#define FL_IMMUNE_WATER 131072 -#define FL_IMMUNE_SLIME 262144 -#define FL_IMMUNE_LAVA 524288 - -#define CHAN_VOICE 2 -#define CHAN_BODY 4 - -#define ATTN_NORM 1 - -void PF_WaterMove (void) -{ - edict_t *self; - int flags; - int waterlevel; - int watertype; - float drownlevel; - float damage = 0.0; - - self = PROG_TO_EDICT(pr_global_struct->self); - - if (self->v.movetype == MOVETYPE_NOCLIP) - { - self->v.air_finished = sv.time + 12; - G_FLOAT(OFS_RETURN) = damage; - return; - } - - if (self->v.health < 0) - { - G_FLOAT(OFS_RETURN) = damage; - return; - } - - if (self->v.deadflag == DEAD_NO) - drownlevel = 3; - else - drownlevel = 1; - - flags = (int)self->v.flags; - waterlevel = (int)self->v.waterlevel; - watertype = (int)self->v.watertype; - - if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE))) - if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel)) - { - if (self->v.air_finished < sv.time) - if (self->v.pain_finished < sv.time) - { - self->v.dmg = self->v.dmg + 2; - if (self->v.dmg > 15) - self->v.dmg = 10; -// T_Damage (self, world, world, self.dmg, 0, FALSE); - damage = self->v.dmg; - self->v.pain_finished = sv.time + 1.0; - } - } - else - { - if (self->v.air_finished < sv.time) -// sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM); - else if (self->v.air_finished < sv.time + 9) -// sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM); - self->v.air_finished = sv.time + 12.0; - self->v.dmg = 2; - } - - if (!waterlevel) - { - if (flags & FL_INWATER) - { - // play leave water sound -// sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM); - self->v.flags = (float)(flags &~FL_INWATER); - } - self->v.air_finished = sv.time + 12.0; - G_FLOAT(OFS_RETURN) = damage; - return; - } - - if (watertype == CONTENT_LAVA) - { // do damage - if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE))) - if (self->v.dmgtime < sv.time) - { - if (self->v.radsuit_finished < sv.time) - self->v.dmgtime = sv.time + 0.2; - else - self->v.dmgtime = sv.time + 1.0; -// T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE); - damage = (float)(10*waterlevel); - } - } - else if (watertype == CONTENT_SLIME) - { // do damage - if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE))) - if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time) - { - self->v.dmgtime = sv.time + 1.0; -// T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE); - damage = (float)(4*waterlevel); - } - } - - if ( !(flags & FL_INWATER) ) - { - -// player enter water sound - if (watertype == CONTENT_LAVA) -// sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM); - if (watertype == CONTENT_WATER) -// sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM); - if (watertype == CONTENT_SLIME) -// sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM); - SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM); - - self->v.flags = (float)(flags | FL_INWATER); - self->v.dmgtime = 0; - } - - if (! (flags & FL_WATERJUMP) ) - { -// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity; - VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity); - } - - G_FLOAT(OFS_RETURN) = damage; -} - - -void PF_sin (void) -{ - G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); -} - -void PF_cos (void) -{ - G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); -} - -void PF_sqrt (void) -{ - G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); -} -#endif - -void PF_Fixme (void) -{ - PR_RunError ("unimplemented bulitin"); -} - - - -builtin_t pr_builtin[] = -{ -PF_Fixme, -PF_makevectors, // void(entity e) makevectors = #1; -PF_setorigin, // void(entity e, vector o) setorigin = #2; -PF_setmodel, // void(entity e, string m) setmodel = #3; -PF_setsize, // void(entity e, vector min, vector max) setsize = #4; -PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5; -PF_break, // void() break = #6; -PF_random, // float() random = #7; -PF_sound, // void(entity e, float chan, string samp) sound = #8; -PF_normalize, // vector(vector v) normalize = #9; -PF_error, // void(string e) error = #10; -PF_objerror, // void(string e) objerror = #11; -PF_vlen, // float(vector v) vlen = #12; -PF_vectoyaw, // float(vector v) vectoyaw = #13; -PF_Spawn, // entity() spawn = #14; -PF_Remove, // void(entity e) remove = #15; -PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16; -PF_checkclient, // entity() clientlist = #17; -PF_Find, // entity(entity start, .string fld, string match) find = #18; -PF_precache_sound, // void(string s) precache_sound = #19; -PF_precache_model, // void(string s) precache_model = #20; -PF_stuffcmd, // void(entity client, string s)stuffcmd = #21; -PF_findradius, // entity(vector org, float rad) findradius = #22; -PF_bprint, // void(string s) bprint = #23; -PF_sprint, // void(entity client, string s) sprint = #24; -PF_dprint, // void(string s) dprint = #25; -PF_ftos, // void(string s) ftos = #26; -PF_vtos, // void(string s) vtos = #27; -PF_coredump, -PF_traceon, -PF_traceoff, -PF_eprint, // void(entity e) debug print an entire entity -PF_walkmove, // float(float yaw, float dist) walkmove -PF_Fixme, // float(float yaw, float dist) walkmove -PF_droptofloor, -PF_lightstyle, -PF_rint, -PF_floor, -PF_ceil, -PF_Fixme, -PF_checkbottom, -PF_pointcontents, -PF_Fixme, -PF_fabs, -PF_aim, -PF_cvar, -PF_localcmd, -PF_nextent, -PF_particle, -PF_changeyaw, -PF_Fixme, -PF_vectoangles, - -PF_WriteByte, -PF_WriteChar, -PF_WriteShort, -PF_WriteLong, -PF_WriteCoord, -PF_WriteAngle, -PF_WriteString, -PF_WriteEntity, - -#ifdef QUAKE2 -PF_sin, -PF_cos, -PF_sqrt, -PF_changepitch, -PF_TraceToss, -PF_etos, -PF_WaterMove, -#else -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -#endif - -SV_MoveToGoal, -PF_precache_file, -PF_makestatic, - -PF_changelevel, -PF_Fixme, - -PF_cvar_set, -PF_centerprint, - -PF_ambientsound, - -PF_precache_model, -PF_precache_sound, // precache_sound2 is different only for qcc -PF_precache_file, - -PF_setspawnparms -}; - -builtin_t *pr_builtins = pr_builtin; -int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) + +/* +=============================================================================== + + BUILT-IN FUNCTIONS + +=============================================================================== +*/ + +char *PF_VarString (int first) +{ + int i; + static char out[256]; + + out[0] = 0; + for (i=first ; is_name,s); + ed = PROG_TO_EDICT(pr_global_struct->self); + ED_Print (ed); + + Host_Error ("Program error"); +} + +/* +================= +PF_objerror + +Dumps out self, then an error message. The program is aborted and self is +removed, but the level can continue. + +objerror(value) +================= +*/ +void PF_objerror (void) +{ + char *s; + edict_t *ed; + + s = PF_VarString(0); + Con_Printf ("======OBJECT ERROR in %s:\n%s\n" + ,pr_strings + pr_xfunction->s_name,s); + ed = PROG_TO_EDICT(pr_global_struct->self); + ED_Print (ed); + ED_Free (ed); + + Host_Error ("Program error"); +} + + + +/* +============== +PF_makevectors + +Writes new values for v_forward, v_up, and v_right based on angles +makevectors(vector) +============== +*/ +void PF_makevectors (void) +{ + AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); +} + +/* +================= +PF_setorigin + +This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported. + +setorigin (entity, origin) +================= +*/ +void PF_setorigin (void) +{ + edict_t *e; + float *org; + + e = G_EDICT(OFS_PARM0); + org = G_VECTOR(OFS_PARM1); + VectorCopy (org, e->v.origin); + SV_LinkEdict (e, false); +} + + +void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) +{ + float *angles; + vec3_t rmin, rmax; + float bounds[2][3]; + float xvector[2], yvector[2]; + float a; + vec3_t base, transformed; + int i, j, k, l; + + for (i=0 ; i<3 ; i++) + if (min[i] > max[i]) + PR_RunError ("backwards mins/maxs"); + + rotate = false; // FIXME: implement rotation properly again + + if (!rotate) + { + VectorCopy (min, rmin); + VectorCopy (max, rmax); + } + else + { + // find min / max for rotations + angles = e->v.angles; + + a = angles[1]/180 * M_PI; + + xvector[0] = cos(a); + xvector[1] = sin(a); + yvector[0] = -sin(a); + yvector[1] = cos(a); + + VectorCopy (min, bounds[0]); + VectorCopy (max, bounds[1]); + + rmin[0] = rmin[1] = rmin[2] = 9999; + rmax[0] = rmax[1] = rmax[2] = -9999; + + for (i=0 ; i<= 1 ; i++) + { + base[0] = bounds[i][0]; + for (j=0 ; j<= 1 ; j++) + { + base[1] = bounds[j][1]; + for (k=0 ; k<= 1 ; k++) + { + base[2] = bounds[k][2]; + + // transform the point + transformed[0] = xvector[0]*base[0] + yvector[0]*base[1]; + transformed[1] = xvector[1]*base[0] + yvector[1]*base[1]; + transformed[2] = base[2]; + + for (l=0 ; l<3 ; l++) + { + if (transformed[l] < rmin[l]) + rmin[l] = transformed[l]; + if (transformed[l] > rmax[l]) + rmax[l] = transformed[l]; + } + } + } + } + } + +// set derived values + VectorCopy (rmin, e->v.mins); + VectorCopy (rmax, e->v.maxs); + VectorSubtract (max, min, e->v.size); + + SV_LinkEdict (e, false); +} + +/* +================= +PF_setsize + +the size box is rotated by the current angle + +setsize (entity, minvector, maxvector) +================= +*/ +void PF_setsize (void) +{ + edict_t *e; + float *min, *max; + + e = G_EDICT(OFS_PARM0); + min = G_VECTOR(OFS_PARM1); + max = G_VECTOR(OFS_PARM2); + SetMinMaxSize (e, min, max, false); +} + + +/* +================= +PF_setmodel + +setmodel(entity, model) +================= +*/ +void PF_setmodel (void) +{ + edict_t *e; + char *m, **check; + model_t *mod; + int i; + + e = G_EDICT(OFS_PARM0); + m = G_STRING(OFS_PARM1); + +// check to see if model was properly precached + for (i=0, check = sv.model_precache ; *check ; i++, check++) + if (!strcmp(*check, m)) + break; + + if (!*check) + PR_RunError ("no precache: %s\n", m); + + + e->v.model = m - pr_strings; + e->v.modelindex = i; //SV_ModelIndex (m); + + mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true); + + if (mod) + SetMinMaxSize (e, mod->mins, mod->maxs, true); + else + SetMinMaxSize (e, vec3_origin, vec3_origin, true); +} + +/* +================= +PF_bprint + +broadcast print to everyone on server + +bprint(value) +================= +*/ +void PF_bprint (void) +{ + char *s; + + s = PF_VarString(0); + SV_BroadcastPrintf ("%s", s); +} + +/* +================= +PF_sprint + +single print to a specific client + +sprint(clientent, value) +================= +*/ +void PF_sprint (void) +{ + char *s; + client_t *client; + int entnum; + + entnum = G_EDICTNUM(OFS_PARM0); + s = PF_VarString(1); + + if (entnum < 1 || entnum > svs.maxclients) + { + Con_Printf ("tried to sprint to a non-client\n"); + return; + } + + client = &svs.clients[entnum-1]; + + MSG_WriteChar (&client->message,svc_print); + MSG_WriteString (&client->message, s ); +} + + +/* +================= +PF_centerprint + +single print to a specific client + +centerprint(clientent, value) +================= +*/ +void PF_centerprint (void) +{ + char *s; + client_t *client; + int entnum; + + entnum = G_EDICTNUM(OFS_PARM0); + s = PF_VarString(1); + + if (entnum < 1 || entnum > svs.maxclients) + { + Con_Printf ("tried to sprint to a non-client\n"); + return; + } + + client = &svs.clients[entnum-1]; + + MSG_WriteChar (&client->message,svc_centerprint); + MSG_WriteString (&client->message, s ); +} + + +/* +================= +PF_normalize + +vector normalize(vector) +================= +*/ +void PF_normalize (void) +{ + float *value1; + vec3_t newvalue; + float new; + + value1 = G_VECTOR(OFS_PARM0); + + new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; + new = sqrt(new); + + if (new == 0) + newvalue[0] = newvalue[1] = newvalue[2] = 0; + else + { + new = 1/new; + newvalue[0] = value1[0] * new; + newvalue[1] = value1[1] * new; + newvalue[2] = value1[2] * new; + } + + VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); +} + +/* +================= +PF_vlen + +scalar vlen(vector) +================= +*/ +void PF_vlen (void) +{ + float *value1; + float new; + + value1 = G_VECTOR(OFS_PARM0); + + new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; + new = sqrt(new); + + G_FLOAT(OFS_RETURN) = new; +} + +/* +================= +PF_vectoyaw + +float vectoyaw(vector) +================= +*/ +void PF_vectoyaw (void) +{ + float *value1; + float yaw; + + value1 = G_VECTOR(OFS_PARM0); + + if (value1[1] == 0 && value1[0] == 0) + yaw = 0; + else + { + yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + } + + G_FLOAT(OFS_RETURN) = yaw; +} + + +/* +================= +PF_vectoangles + +vector vectoangles(vector) +================= +*/ +void PF_vectoangles (void) +{ + float *value1; + float forward; + float yaw, pitch; + + value1 = G_VECTOR(OFS_PARM0); + + if (value1[1] == 0 && value1[0] == 0) + { + yaw = 0; + if (value1[2] > 0) + pitch = 90; + else + pitch = 270; + } + else + { + yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + + forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); + pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); + if (pitch < 0) + pitch += 360; + } + + G_FLOAT(OFS_RETURN+0) = pitch; + G_FLOAT(OFS_RETURN+1) = yaw; + G_FLOAT(OFS_RETURN+2) = 0; +} + +/* +================= +PF_Random + +Returns a number from 0<= num < 1 + +random() +================= +*/ +void PF_random (void) +{ + float num; + + num = (rand ()&0x7fff) / ((float)0x7fff); + + G_FLOAT(OFS_RETURN) = num; +} + +/* +================= +PF_particle + +particle(origin, color, count) +================= +*/ +void PF_particle (void) +{ + float *org, *dir; + float color; + float count; + + org = G_VECTOR(OFS_PARM0); + dir = G_VECTOR(OFS_PARM1); + color = G_FLOAT(OFS_PARM2); + count = G_FLOAT(OFS_PARM3); + SV_StartParticle (org, dir, color, count); +} + + +/* +================= +PF_ambientsound + +================= +*/ +void PF_ambientsound (void) +{ + char **check; + char *samp; + float *pos; + float vol, attenuation; + int i, soundnum; + + pos = G_VECTOR (OFS_PARM0); + samp = G_STRING(OFS_PARM1); + vol = G_FLOAT(OFS_PARM2); + attenuation = G_FLOAT(OFS_PARM3); + +// check to see if samp was properly precached + for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++) + if (!strcmp(*check,samp)) + break; + + if (!*check) + { + Con_Printf ("no precache: %s\n", samp); + return; + } + +// add an svc_spawnambient command to the level signon packet + + MSG_WriteByte (&sv.signon,svc_spawnstaticsound); + for (i=0 ; i<3 ; i++) + MSG_WriteCoord(&sv.signon, pos[i]); + + MSG_WriteByte (&sv.signon, soundnum); + + MSG_WriteByte (&sv.signon, vol*255); + MSG_WriteByte (&sv.signon, attenuation*64); + +} + +/* +================= +PF_sound + +Each entity can have eight independant sound sources, like voice, +weapon, feet, etc. + +Channel 0 is an auto-allocate channel, the others override anything +allready running on that entity/channel pair. + +An attenuation of 0 will play full volume everywhere in the level. +Larger attenuations will drop off. + +================= +*/ +void PF_sound (void) +{ + char *sample; + int channel; + edict_t *entity; + int volume; + float attenuation; + + entity = G_EDICT(OFS_PARM0); + channel = G_FLOAT(OFS_PARM1); + sample = G_STRING(OFS_PARM2); + volume = G_FLOAT(OFS_PARM3) * 255; + attenuation = G_FLOAT(OFS_PARM4); + + if (volume < 0 || volume > 255) + Sys_Error ("SV_StartSound: volume = %i", volume); + + if (attenuation < 0 || attenuation > 4) + Sys_Error ("SV_StartSound: attenuation = %f", attenuation); + + if (channel < 0 || channel > 7) + Sys_Error ("SV_StartSound: channel = %i", channel); + + SV_StartSound (entity, channel, sample, volume, attenuation); +} + +/* +================= +PF_break + +break() +================= +*/ +void PF_break (void) +{ +Con_Printf ("break statement\n"); +*(int *)-4 = 0; // dump to debugger +// PR_RunError ("break statement"); +} + +/* +================= +PF_traceline + +Used for use tracing and shot targeting +Traces are blocked by bbox and exact bsp entityes, and also slide box entities +if the tryents flag is set. + +traceline (vector1, vector2, tryents) +================= +*/ +void PF_traceline (void) +{ + float *v1, *v2; + trace_t trace; + int nomonsters; + edict_t *ent; + + v1 = G_VECTOR(OFS_PARM0); + v2 = G_VECTOR(OFS_PARM1); + nomonsters = G_FLOAT(OFS_PARM2); + ent = G_EDICT(OFS_PARM3); + + trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); + + pr_global_struct->trace_allsolid = trace.allsolid; + pr_global_struct->trace_startsolid = trace.startsolid; + pr_global_struct->trace_fraction = trace.fraction; + pr_global_struct->trace_inwater = trace.inwater; + pr_global_struct->trace_inopen = trace.inopen; + VectorCopy (trace.endpos, pr_global_struct->trace_endpos); + VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); + pr_global_struct->trace_plane_dist = trace.plane.dist; + if (trace.ent) + pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); + else + pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); +} + + +#ifdef QUAKE2 +extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); + +void PF_TraceToss (void) +{ + trace_t trace; + edict_t *ent; + edict_t *ignore; + + ent = G_EDICT(OFS_PARM0); + ignore = G_EDICT(OFS_PARM1); + + trace = SV_Trace_Toss (ent, ignore); + + pr_global_struct->trace_allsolid = trace.allsolid; + pr_global_struct->trace_startsolid = trace.startsolid; + pr_global_struct->trace_fraction = trace.fraction; + pr_global_struct->trace_inwater = trace.inwater; + pr_global_struct->trace_inopen = trace.inopen; + VectorCopy (trace.endpos, pr_global_struct->trace_endpos); + VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); + pr_global_struct->trace_plane_dist = trace.plane.dist; + if (trace.ent) + pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); + else + pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); +} +#endif + + +/* +================= +PF_checkpos + +Returns true if the given entity can move to the given position from it's +current position by walking or rolling. +FIXME: make work... +scalar checkpos (entity, vector) +================= +*/ +void PF_checkpos (void) +{ +} + +//============================================================================ + +byte checkpvs[MAX_MAP_LEAFS/8]; + +int PF_newcheckclient (int check) +{ + int i; + byte *pvs; + edict_t *ent; + mleaf_t *leaf; + vec3_t org; + +// cycle to the next one + + if (check < 1) + check = 1; + if (check > svs.maxclients) + check = svs.maxclients; + + if (check == svs.maxclients) + i = 1; + else + i = check + 1; + + for ( ; ; i++) + { + if (i == svs.maxclients+1) + i = 1; + + ent = EDICT_NUM(i); + + if (i == check) + break; // didn't find anything else + + if (ent->free) + continue; + if (ent->v.health <= 0) + continue; + if ((int)ent->v.flags & FL_NOTARGET) + continue; + + // anything that is a client, or has a client as an enemy + break; + } + +// get the PVS for the entity + VectorAdd (ent->v.origin, ent->v.view_ofs, org); + leaf = Mod_PointInLeaf (org, sv.worldmodel); + pvs = Mod_LeafPVS (leaf, sv.worldmodel); + memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 ); + + return i; +} + +/* +================= +PF_checkclient + +Returns a client (or object that has a client enemy) that would be a +valid target. + +If there are more than one valid options, they are cycled each frame + +If (self.origin + self.viewofs) is not in the PVS of the current target, +it is not returned at all. + +name checkclient () +================= +*/ +#define MAX_CHECK 16 +int c_invis, c_notvis; +void PF_checkclient (void) +{ + edict_t *ent, *self; + mleaf_t *leaf; + int l; + vec3_t view; + +// find a new check if on a new frame + if (sv.time - sv.lastchecktime >= 0.1) + { + sv.lastcheck = PF_newcheckclient (sv.lastcheck); + sv.lastchecktime = sv.time; + } + +// return check if it might be visible + ent = EDICT_NUM(sv.lastcheck); + if (ent->free || ent->v.health <= 0) + { + RETURN_EDICT(sv.edicts); + return; + } + +// if current entity can't possibly see the check entity, return 0 + self = PROG_TO_EDICT(pr_global_struct->self); + VectorAdd (self->v.origin, self->v.view_ofs, view); + leaf = Mod_PointInLeaf (view, sv.worldmodel); + l = (leaf - sv.worldmodel->leafs) - 1; + if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) + { +c_notvis++; + RETURN_EDICT(sv.edicts); + return; + } + +// might be able to see it +c_invis++; + RETURN_EDICT(ent); +} + +//============================================================================ + + +/* +================= +PF_stuffcmd + +Sends text over to the client's execution buffer + +stuffcmd (clientent, value) +================= +*/ +void PF_stuffcmd (void) +{ + int entnum; + char *str; + client_t *old; + + entnum = G_EDICTNUM(OFS_PARM0); + if (entnum < 1 || entnum > svs.maxclients) + PR_RunError ("Parm 0 not a client"); + str = G_STRING(OFS_PARM1); + + old = host_client; + host_client = &svs.clients[entnum-1]; + Host_ClientCommands ("%s", str); + host_client = old; +} + +/* +================= +PF_localcmd + +Sends text over to the client's execution buffer + +localcmd (string) +================= +*/ +void PF_localcmd (void) +{ + char *str; + + str = G_STRING(OFS_PARM0); + Cbuf_AddText (str); +} + +/* +================= +PF_cvar + +float cvar (string) +================= +*/ +void PF_cvar (void) +{ + char *str; + + str = G_STRING(OFS_PARM0); + + G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); +} + +/* +================= +PF_cvar_set + +float cvar (string) +================= +*/ +void PF_cvar_set (void) +{ + char *var, *val; + + var = G_STRING(OFS_PARM0); + val = G_STRING(OFS_PARM1); + + Cvar_Set (var, val); +} + +/* +================= +PF_findradius + +Returns a chain of entities that have origins within a spherical area + +findradius (origin, radius) +================= +*/ +void PF_findradius (void) +{ + edict_t *ent, *chain; + float rad; + float *org; + vec3_t eorg; + int i, j; + + chain = (edict_t *)sv.edicts; + + org = G_VECTOR(OFS_PARM0); + rad = G_FLOAT(OFS_PARM1); + + ent = NEXT_EDICT(sv.edicts); + for (i=1 ; ifree) + continue; + if (ent->v.solid == SOLID_NOT) + continue; + for (j=0 ; j<3 ; j++) + eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5); + if (Length(eorg) > rad) + continue; + + ent->v.chain = EDICT_TO_PROG(chain); + chain = ent; + } + + RETURN_EDICT(chain); +} + + +/* +========= +PF_dprint +========= +*/ +void PF_dprint (void) +{ + Con_DPrintf ("%s",PF_VarString(0)); +} + +char pr_string_temp[128]; + +void PF_ftos (void) +{ + float v; + v = G_FLOAT(OFS_PARM0); + + if (v == (int)v) + sprintf (pr_string_temp, "%d",(int)v); + else + sprintf (pr_string_temp, "%5.1f",v); + G_INT(OFS_RETURN) = pr_string_temp - pr_strings; +} + +void PF_fabs (void) +{ + float v; + v = G_FLOAT(OFS_PARM0); + G_FLOAT(OFS_RETURN) = fabs(v); +} + +void PF_vtos (void) +{ + sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); + G_INT(OFS_RETURN) = pr_string_temp - pr_strings; +} + +#ifdef QUAKE2 +void PF_etos (void) +{ + sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0)); + G_INT(OFS_RETURN) = pr_string_temp - pr_strings; +} +#endif + +void PF_Spawn (void) +{ + edict_t *ed; + ed = ED_Alloc(); + RETURN_EDICT(ed); +} + +void PF_Remove (void) +{ + edict_t *ed; + + ed = G_EDICT(OFS_PARM0); + ED_Free (ed); +} + + +// entity (entity start, .string field, string match) find = #5; +void PF_Find (void) +#ifdef QUAKE2 +{ + int e; + int f; + char *s, *t; + edict_t *ed; + edict_t *first; + edict_t *second; + edict_t *last; + + first = second = last = (edict_t *)sv.edicts; + e = G_EDICTNUM(OFS_PARM0); + f = G_INT(OFS_PARM1); + s = G_STRING(OFS_PARM2); + if (!s) + PR_RunError ("PF_Find: bad search string"); + + for (e++ ; e < sv.num_edicts ; e++) + { + ed = EDICT_NUM(e); + if (ed->free) + continue; + t = E_STRING(ed,f); + if (!t) + continue; + if (!strcmp(t,s)) + { + if (first == (edict_t *)sv.edicts) + first = ed; + else if (second == (edict_t *)sv.edicts) + second = ed; + ed->v.chain = EDICT_TO_PROG(last); + last = ed; + } + } + + if (first != last) + { + if (last != second) + first->v.chain = last->v.chain; + else + first->v.chain = EDICT_TO_PROG(last); + last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts); + if (second && second != last) + second->v.chain = EDICT_TO_PROG(last); + } + RETURN_EDICT(first); +} +#else +{ + int e; + int f; + char *s, *t; + edict_t *ed; + + e = G_EDICTNUM(OFS_PARM0); + f = G_INT(OFS_PARM1); + s = G_STRING(OFS_PARM2); + if (!s) + PR_RunError ("PF_Find: bad search string"); + + for (e++ ; e < sv.num_edicts ; e++) + { + ed = EDICT_NUM(e); + if (ed->free) + continue; + t = E_STRING(ed,f); + if (!t) + continue; + if (!strcmp(t,s)) + { + RETURN_EDICT(ed); + return; + } + } + + RETURN_EDICT(sv.edicts); +} +#endif + +void PR_CheckEmptyString (char *s) +{ + if (s[0] <= ' ') + PR_RunError ("Bad string"); +} + +void PF_precache_file (void) +{ // precache_file is only used to copy files with qcc, it does nothing + G_INT(OFS_RETURN) = G_INT(OFS_PARM0); +} + +void PF_precache_sound (void) +{ + char *s; + int i; + + if (sv.state != ss_loading) + PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); + + s = G_STRING(OFS_PARM0); + G_INT(OFS_RETURN) = G_INT(OFS_PARM0); + PR_CheckEmptyString (s); + + for (i=0 ; iself); + yaw = G_FLOAT(OFS_PARM0); + dist = G_FLOAT(OFS_PARM1); + + if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) + { + G_FLOAT(OFS_RETURN) = 0; + return; + } + + yaw = yaw*M_PI*2 / 360; + + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + +// save program state, because SV_movestep may call other progs + oldf = pr_xfunction; + oldself = pr_global_struct->self; + + G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); + + +// restore program state + pr_xfunction = oldf; + pr_global_struct->self = oldself; +} + +/* +=============== +PF_droptofloor + +void() droptofloor +=============== +*/ +void PF_droptofloor (void) +{ + edict_t *ent; + vec3_t end; + trace_t trace; + + ent = PROG_TO_EDICT(pr_global_struct->self); + + VectorCopy (ent->v.origin, end); + end[2] -= 256; + + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); + + if (trace.fraction == 1 || trace.allsolid) + G_FLOAT(OFS_RETURN) = 0; + else + { + VectorCopy (trace.endpos, ent->v.origin); + SV_LinkEdict (ent, false); + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = EDICT_TO_PROG(trace.ent); + G_FLOAT(OFS_RETURN) = 1; + } +} + +/* +=============== +PF_lightstyle + +void(float style, string value) lightstyle +=============== +*/ +void PF_lightstyle (void) +{ + int style; + char *val; + client_t *client; + int j; + + style = G_FLOAT(OFS_PARM0); + val = G_STRING(OFS_PARM1); + +// change the string in sv + sv.lightstyles[style] = val; + +// send message to all clients on this server + if (sv.state != ss_active) + return; + + for (j=0, client = svs.clients ; jactive || client->spawned) + { + MSG_WriteChar (&client->message, svc_lightstyle); + MSG_WriteChar (&client->message,style); + MSG_WriteString (&client->message, val); + } +} + +void PF_rint (void) +{ + float f; + f = G_FLOAT(OFS_PARM0); + if (f > 0) + G_FLOAT(OFS_RETURN) = (int)(f + 0.5); + else + G_FLOAT(OFS_RETURN) = (int)(f - 0.5); +} +void PF_floor (void) +{ + G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); +} +void PF_ceil (void) +{ + G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); +} + + +/* +============= +PF_checkbottom +============= +*/ +void PF_checkbottom (void) +{ + edict_t *ent; + + ent = G_EDICT(OFS_PARM0); + + G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent); +} + +/* +============= +PF_pointcontents +============= +*/ +void PF_pointcontents (void) +{ + float *v; + + v = G_VECTOR(OFS_PARM0); + + G_FLOAT(OFS_RETURN) = SV_PointContents (v); +} + +/* +============= +PF_nextent + +entity nextent(entity) +============= +*/ +void PF_nextent (void) +{ + int i; + edict_t *ent; + + i = G_EDICTNUM(OFS_PARM0); + while (1) + { + i++; + if (i == sv.num_edicts) + { + RETURN_EDICT(sv.edicts); + return; + } + ent = EDICT_NUM(i); + if (!ent->free) + { + RETURN_EDICT(ent); + return; + } + } +} + +/* +============= +PF_aim + +Pick a vector for the player to shoot along +vector aim(entity, missilespeed) +============= +*/ +cvar_t sv_aim = {"sv_aim", "0.93"}; +void PF_aim (void) +{ + edict_t *ent, *check, *bestent; + vec3_t start, dir, end, bestdir; + int i, j; + trace_t tr; + float dist, bestdist; + float speed; + + ent = G_EDICT(OFS_PARM0); + speed = G_FLOAT(OFS_PARM1); + + VectorCopy (ent->v.origin, start); + start[2] += 20; + +// try sending a trace straight + VectorCopy (pr_global_struct->v_forward, dir); + VectorMA (start, 2048, dir, end); + tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); + if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM + && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) ) + { + VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN)); + return; + } + + +// try all possible entities + VectorCopy (dir, bestdir); + bestdist = sv_aim.value; + bestent = NULL; + + check = NEXT_EDICT(sv.edicts); + for (i=1 ; iv.takedamage != DAMAGE_AIM) + continue; + if (check == ent) + continue; + if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team) + continue; // don't aim at teammate + for (j=0 ; j<3 ; j++) + end[j] = check->v.origin[j] + + 0.5*(check->v.mins[j] + check->v.maxs[j]); + VectorSubtract (end, start, dir); + VectorNormalize (dir); + dist = DotProduct (dir, pr_global_struct->v_forward); + if (dist < bestdist) + continue; // to far to turn + tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); + if (tr.ent == check) + { // can shoot at this one + bestdist = dist; + bestent = check; + } + } + + if (bestent) + { + VectorSubtract (bestent->v.origin, ent->v.origin, dir); + dist = DotProduct (dir, pr_global_struct->v_forward); + VectorScale (pr_global_struct->v_forward, dist, end); + end[2] = dir[2]; + VectorNormalize (end); + VectorCopy (end, G_VECTOR(OFS_RETURN)); + } + else + { + VectorCopy (bestdir, G_VECTOR(OFS_RETURN)); + } +} + +/* +============== +PF_changeyaw + +This was a major timewaster in progs, so it was converted to C +============== +*/ +void PF_changeyaw (void) +{ + edict_t *ent; + float ideal, current, move, speed; + + ent = PROG_TO_EDICT(pr_global_struct->self); + current = anglemod( ent->v.angles[1] ); + ideal = ent->v.ideal_yaw; + speed = ent->v.yaw_speed; + + if (current == ideal) + return; + move = ideal - current; + if (ideal > current) + { + if (move >= 180) + move = move - 360; + } + else + { + if (move <= -180) + move = move + 360; + } + if (move > 0) + { + if (move > speed) + move = speed; + } + else + { + if (move < -speed) + move = -speed; + } + + ent->v.angles[1] = anglemod (current + move); +} + +#ifdef QUAKE2 +/* +============== +PF_changepitch +============== +*/ +void PF_changepitch (void) +{ + edict_t *ent; + float ideal, current, move, speed; + + ent = G_EDICT(OFS_PARM0); + current = anglemod( ent->v.angles[0] ); + ideal = ent->v.idealpitch; + speed = ent->v.pitch_speed; + + if (current == ideal) + return; + move = ideal - current; + if (ideal > current) + { + if (move >= 180) + move = move - 360; + } + else + { + if (move <= -180) + move = move + 360; + } + if (move > 0) + { + if (move > speed) + move = speed; + } + else + { + if (move < -speed) + move = -speed; + } + + ent->v.angles[0] = anglemod (current + move); +} +#endif + +/* +=============================================================================== + +MESSAGE WRITING + +=============================================================================== +*/ + +#define MSG_BROADCAST 0 // unreliable to all +#define MSG_ONE 1 // reliable to one (msg_entity) +#define MSG_ALL 2 // reliable to all +#define MSG_INIT 3 // write to the init string + +sizebuf_t *WriteDest (void) +{ + int entnum; + int dest; + edict_t *ent; + + dest = G_FLOAT(OFS_PARM0); + switch (dest) + { + case MSG_BROADCAST: + return &sv.datagram; + + case MSG_ONE: + ent = PROG_TO_EDICT(pr_global_struct->msg_entity); + entnum = NUM_FOR_EDICT(ent); + if (entnum < 1 || entnum > svs.maxclients) + PR_RunError ("WriteDest: not a client"); + return &svs.clients[entnum-1].message; + + case MSG_ALL: + return &sv.reliable_datagram; + + case MSG_INIT: + return &sv.signon; + + default: + PR_RunError ("WriteDest: bad destination"); + break; + } + + return NULL; +} + +void PF_WriteByte (void) +{ + MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteChar (void) +{ + MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteShort (void) +{ + MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteLong (void) +{ + MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteAngle (void) +{ + MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteCoord (void) +{ + MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1)); +} + +void PF_WriteString (void) +{ + MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1)); +} + + +void PF_WriteEntity (void) +{ + MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1)); +} + +//============================================================================= + +int SV_ModelIndex (char *name); + +void PF_makestatic (void) +{ + edict_t *ent; + int i; + + ent = G_EDICT(OFS_PARM0); + + MSG_WriteByte (&sv.signon,svc_spawnstatic); + + MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model)); + + MSG_WriteByte (&sv.signon, ent->v.frame); + MSG_WriteByte (&sv.signon, ent->v.colormap); + MSG_WriteByte (&sv.signon, ent->v.skin); + for (i=0 ; i<3 ; i++) + { + MSG_WriteCoord(&sv.signon, ent->v.origin[i]); + MSG_WriteAngle(&sv.signon, ent->v.angles[i]); + } + +// throw the entity away now + ED_Free (ent); +} + +//============================================================================= + +/* +============== +PF_setspawnparms +============== +*/ +void PF_setspawnparms (void) +{ + edict_t *ent; + int i; + client_t *client; + + ent = G_EDICT(OFS_PARM0); + i = NUM_FOR_EDICT(ent); + if (i < 1 || i > svs.maxclients) + PR_RunError ("Entity is not a client"); + + // copy spawn parms out of the client_t + client = svs.clients + (i-1); + + for (i=0 ; i< NUM_SPAWN_PARMS ; i++) + (&pr_global_struct->parm1)[i] = client->spawn_parms[i]; +} + +/* +============== +PF_changelevel +============== +*/ +void PF_changelevel (void) +{ +#ifdef QUAKE2 + char *s1, *s2; + + if (svs.changelevel_issued) + return; + svs.changelevel_issued = true; + + s1 = G_STRING(OFS_PARM0); + s2 = G_STRING(OFS_PARM1); + + if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE)) + Cbuf_AddText (va("changelevel %s %s\n",s1, s2)); + else + Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2)); +#else + char *s; + +// make sure we don't issue two changelevels + if (svs.changelevel_issued) + return; + svs.changelevel_issued = true; + + s = G_STRING(OFS_PARM0); + Cbuf_AddText (va("changelevel %s\n",s)); +#endif +} + + +#ifdef QUAKE2 + +#define CONTENT_WATER -3 +#define CONTENT_SLIME -4 +#define CONTENT_LAVA -5 + +#define FL_IMMUNE_WATER 131072 +#define FL_IMMUNE_SLIME 262144 +#define FL_IMMUNE_LAVA 524288 + +#define CHAN_VOICE 2 +#define CHAN_BODY 4 + +#define ATTN_NORM 1 + +void PF_WaterMove (void) +{ + edict_t *self; + int flags; + int waterlevel; + int watertype; + float drownlevel; + float damage = 0.0; + + self = PROG_TO_EDICT(pr_global_struct->self); + + if (self->v.movetype == MOVETYPE_NOCLIP) + { + self->v.air_finished = sv.time + 12; + G_FLOAT(OFS_RETURN) = damage; + return; + } + + if (self->v.health < 0) + { + G_FLOAT(OFS_RETURN) = damage; + return; + } + + if (self->v.deadflag == DEAD_NO) + drownlevel = 3; + else + drownlevel = 1; + + flags = (int)self->v.flags; + waterlevel = (int)self->v.waterlevel; + watertype = (int)self->v.watertype; + + if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE))) + if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel)) + { + if (self->v.air_finished < sv.time) + if (self->v.pain_finished < sv.time) + { + self->v.dmg = self->v.dmg + 2; + if (self->v.dmg > 15) + self->v.dmg = 10; +// T_Damage (self, world, world, self.dmg, 0, FALSE); + damage = self->v.dmg; + self->v.pain_finished = sv.time + 1.0; + } + } + else + { + if (self->v.air_finished < sv.time) +// sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM); + else if (self->v.air_finished < sv.time + 9) +// sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM); + self->v.air_finished = sv.time + 12.0; + self->v.dmg = 2; + } + + if (!waterlevel) + { + if (flags & FL_INWATER) + { + // play leave water sound +// sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM); + self->v.flags = (float)(flags &~FL_INWATER); + } + self->v.air_finished = sv.time + 12.0; + G_FLOAT(OFS_RETURN) = damage; + return; + } + + if (watertype == CONTENT_LAVA) + { // do damage + if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE))) + if (self->v.dmgtime < sv.time) + { + if (self->v.radsuit_finished < sv.time) + self->v.dmgtime = sv.time + 0.2; + else + self->v.dmgtime = sv.time + 1.0; +// T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE); + damage = (float)(10*waterlevel); + } + } + else if (watertype == CONTENT_SLIME) + { // do damage + if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE))) + if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time) + { + self->v.dmgtime = sv.time + 1.0; +// T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE); + damage = (float)(4*waterlevel); + } + } + + if ( !(flags & FL_INWATER) ) + { + +// player enter water sound + if (watertype == CONTENT_LAVA) +// sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM); + if (watertype == CONTENT_WATER) +// sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM); + if (watertype == CONTENT_SLIME) +// sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM); + SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM); + + self->v.flags = (float)(flags | FL_INWATER); + self->v.dmgtime = 0; + } + + if (! (flags & FL_WATERJUMP) ) + { +// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity; + VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity); + } + + G_FLOAT(OFS_RETURN) = damage; +} + + +void PF_sin (void) +{ + G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); +} + +void PF_cos (void) +{ + G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); +} + +void PF_sqrt (void) +{ + G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); +} +#endif + +void PF_Fixme (void) +{ + PR_RunError ("unimplemented bulitin"); +} + + + +builtin_t pr_builtin[] = +{ +PF_Fixme, +PF_makevectors, // void(entity e) makevectors = #1; +PF_setorigin, // void(entity e, vector o) setorigin = #2; +PF_setmodel, // void(entity e, string m) setmodel = #3; +PF_setsize, // void(entity e, vector min, vector max) setsize = #4; +PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5; +PF_break, // void() break = #6; +PF_random, // float() random = #7; +PF_sound, // void(entity e, float chan, string samp) sound = #8; +PF_normalize, // vector(vector v) normalize = #9; +PF_error, // void(string e) error = #10; +PF_objerror, // void(string e) objerror = #11; +PF_vlen, // float(vector v) vlen = #12; +PF_vectoyaw, // float(vector v) vectoyaw = #13; +PF_Spawn, // entity() spawn = #14; +PF_Remove, // void(entity e) remove = #15; +PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16; +PF_checkclient, // entity() clientlist = #17; +PF_Find, // entity(entity start, .string fld, string match) find = #18; +PF_precache_sound, // void(string s) precache_sound = #19; +PF_precache_model, // void(string s) precache_model = #20; +PF_stuffcmd, // void(entity client, string s)stuffcmd = #21; +PF_findradius, // entity(vector org, float rad) findradius = #22; +PF_bprint, // void(string s) bprint = #23; +PF_sprint, // void(entity client, string s) sprint = #24; +PF_dprint, // void(string s) dprint = #25; +PF_ftos, // void(string s) ftos = #26; +PF_vtos, // void(string s) vtos = #27; +PF_coredump, +PF_traceon, +PF_traceoff, +PF_eprint, // void(entity e) debug print an entire entity +PF_walkmove, // float(float yaw, float dist) walkmove +PF_Fixme, // float(float yaw, float dist) walkmove +PF_droptofloor, +PF_lightstyle, +PF_rint, +PF_floor, +PF_ceil, +PF_Fixme, +PF_checkbottom, +PF_pointcontents, +PF_Fixme, +PF_fabs, +PF_aim, +PF_cvar, +PF_localcmd, +PF_nextent, +PF_particle, +PF_changeyaw, +PF_Fixme, +PF_vectoangles, + +PF_WriteByte, +PF_WriteChar, +PF_WriteShort, +PF_WriteLong, +PF_WriteCoord, +PF_WriteAngle, +PF_WriteString, +PF_WriteEntity, + +#ifdef QUAKE2 +PF_sin, +PF_cos, +PF_sqrt, +PF_changepitch, +PF_TraceToss, +PF_etos, +PF_WaterMove, +#else +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +PF_Fixme, +#endif + +SV_MoveToGoal, +PF_precache_file, +PF_makestatic, + +PF_changelevel, +PF_Fixme, + +PF_cvar_set, +PF_centerprint, + +PF_ambientsound, + +PF_precache_model, +PF_precache_sound, // precache_sound2 is different only for qcc +PF_precache_file, + +PF_setspawnparms +}; + +builtin_t *pr_builtins = pr_builtin; +int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); + diff --git a/WinQuake/pr_comp.h b/WinQuake/pr_comp.h index b237ed5..fb09251 100644 --- a/WinQuake/pr_comp.h +++ b/WinQuake/pr_comp.h @@ -1,180 +1,180 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// this file is shared by quake and qcc - -typedef int func_t; -typedef int string_t; - -typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t; - - -#define OFS_NULL 0 -#define OFS_RETURN 1 -#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors -#define OFS_PARM1 7 -#define OFS_PARM2 10 -#define OFS_PARM3 13 -#define OFS_PARM4 16 -#define OFS_PARM5 19 -#define OFS_PARM6 22 -#define OFS_PARM7 25 -#define RESERVED_OFS 28 - - -enum { - OP_DONE, - OP_MUL_F, - OP_MUL_V, - OP_MUL_FV, - OP_MUL_VF, - OP_DIV_F, - OP_ADD_F, - OP_ADD_V, - OP_SUB_F, - OP_SUB_V, - - OP_EQ_F, - OP_EQ_V, - OP_EQ_S, - OP_EQ_E, - OP_EQ_FNC, - - OP_NE_F, - OP_NE_V, - OP_NE_S, - OP_NE_E, - OP_NE_FNC, - - OP_LE, - OP_GE, - OP_LT, - OP_GT, - - OP_LOAD_F, - OP_LOAD_V, - OP_LOAD_S, - OP_LOAD_ENT, - OP_LOAD_FLD, - OP_LOAD_FNC, - - OP_ADDRESS, - - OP_STORE_F, - OP_STORE_V, - OP_STORE_S, - OP_STORE_ENT, - OP_STORE_FLD, - OP_STORE_FNC, - - OP_STOREP_F, - OP_STOREP_V, - OP_STOREP_S, - OP_STOREP_ENT, - OP_STOREP_FLD, - OP_STOREP_FNC, - - OP_RETURN, - OP_NOT_F, - OP_NOT_V, - OP_NOT_S, - OP_NOT_ENT, - OP_NOT_FNC, - OP_IF, - OP_IFNOT, - OP_CALL0, - OP_CALL1, - OP_CALL2, - OP_CALL3, - OP_CALL4, - OP_CALL5, - OP_CALL6, - OP_CALL7, - OP_CALL8, - OP_STATE, - OP_GOTO, - OP_AND, - OP_OR, - - OP_BITAND, - OP_BITOR -}; - - -typedef struct statement_s -{ - unsigned short op; - short a,b,c; -} dstatement_t; - -typedef struct -{ - unsigned short type; // if DEF_SAVEGLOBGAL bit is set - // the variable needs to be saved in savegames - unsigned short ofs; - int s_name; -} ddef_t; -#define DEF_SAVEGLOBAL (1<<15) - -#define MAX_PARMS 8 - -typedef struct -{ - int first_statement; // negative numbers are builtins - int parm_start; - int locals; // total ints of parms + locals - - int profile; // runtime - - int s_name; - int s_file; // source file defined in - - int numparms; - byte parm_size[MAX_PARMS]; -} dfunction_t; - - -#define PROG_VERSION 6 -typedef struct -{ - int version; - int crc; // check of header file - - int ofs_statements; - int numstatements; // statement 0 is an error - - int ofs_globaldefs; - int numglobaldefs; - - int ofs_fielddefs; - int numfielddefs; - - int ofs_functions; - int numfunctions; // function 0 is an empty - - int ofs_strings; - int numstrings; // first string is a null string - - int ofs_globals; - int numglobals; - - int entityfields; -} dprograms_t; - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// this file is shared by quake and qcc + +typedef int func_t; +typedef int string_t; + +typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t; + + +#define OFS_NULL 0 +#define OFS_RETURN 1 +#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors +#define OFS_PARM1 7 +#define OFS_PARM2 10 +#define OFS_PARM3 13 +#define OFS_PARM4 16 +#define OFS_PARM5 19 +#define OFS_PARM6 22 +#define OFS_PARM7 25 +#define RESERVED_OFS 28 + + +enum { + OP_DONE, + OP_MUL_F, + OP_MUL_V, + OP_MUL_FV, + OP_MUL_VF, + OP_DIV_F, + OP_ADD_F, + OP_ADD_V, + OP_SUB_F, + OP_SUB_V, + + OP_EQ_F, + OP_EQ_V, + OP_EQ_S, + OP_EQ_E, + OP_EQ_FNC, + + OP_NE_F, + OP_NE_V, + OP_NE_S, + OP_NE_E, + OP_NE_FNC, + + OP_LE, + OP_GE, + OP_LT, + OP_GT, + + OP_LOAD_F, + OP_LOAD_V, + OP_LOAD_S, + OP_LOAD_ENT, + OP_LOAD_FLD, + OP_LOAD_FNC, + + OP_ADDRESS, + + OP_STORE_F, + OP_STORE_V, + OP_STORE_S, + OP_STORE_ENT, + OP_STORE_FLD, + OP_STORE_FNC, + + OP_STOREP_F, + OP_STOREP_V, + OP_STOREP_S, + OP_STOREP_ENT, + OP_STOREP_FLD, + OP_STOREP_FNC, + + OP_RETURN, + OP_NOT_F, + OP_NOT_V, + OP_NOT_S, + OP_NOT_ENT, + OP_NOT_FNC, + OP_IF, + OP_IFNOT, + OP_CALL0, + OP_CALL1, + OP_CALL2, + OP_CALL3, + OP_CALL4, + OP_CALL5, + OP_CALL6, + OP_CALL7, + OP_CALL8, + OP_STATE, + OP_GOTO, + OP_AND, + OP_OR, + + OP_BITAND, + OP_BITOR +}; + + +typedef struct statement_s +{ + unsigned short op; + short a,b,c; +} dstatement_t; + +typedef struct +{ + unsigned short type; // if DEF_SAVEGLOBGAL bit is set + // the variable needs to be saved in savegames + unsigned short ofs; + int s_name; +} ddef_t; +#define DEF_SAVEGLOBAL (1<<15) + +#define MAX_PARMS 8 + +typedef struct +{ + int first_statement; // negative numbers are builtins + int parm_start; + int locals; // total ints of parms + locals + + int profile; // runtime + + int s_name; + int s_file; // source file defined in + + int numparms; + byte parm_size[MAX_PARMS]; +} dfunction_t; + + +#define PROG_VERSION 6 +typedef struct +{ + int version; + int crc; // check of header file + + int ofs_statements; + int numstatements; // statement 0 is an error + + int ofs_globaldefs; + int numglobaldefs; + + int ofs_fielddefs; + int numfielddefs; + + int ofs_functions; + int numfunctions; // function 0 is an empty + + int ofs_strings; + int numstrings; // first string is a null string + + int ofs_globals; + int numglobals; + + int entityfields; +} dprograms_t; + diff --git a/WinQuake/pr_edict.c b/WinQuake/pr_edict.c index 544e01a..a884b60 100644 --- a/WinQuake/pr_edict.c +++ b/WinQuake/pr_edict.c @@ -1,1106 +1,1106 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_edict.c -- entity dictionary - -#include "quakedef.h" - -dprograms_t *progs; -dfunction_t *pr_functions; -char *pr_strings; -ddef_t *pr_fielddefs; -ddef_t *pr_globaldefs; -dstatement_t *pr_statements; -globalvars_t *pr_global_struct; -float *pr_globals; // same as pr_global_struct -int pr_edict_size; // in bytes - -unsigned short pr_crc; - -int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}; - -ddef_t *ED_FieldAtOfs (int ofs); -qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); - -cvar_t nomonsters = {"nomonsters", "0"}; -cvar_t gamecfg = {"gamecfg", "0"}; -cvar_t scratch1 = {"scratch1", "0"}; -cvar_t scratch2 = {"scratch2", "0"}; -cvar_t scratch3 = {"scratch3", "0"}; -cvar_t scratch4 = {"scratch4", "0"}; -cvar_t savedgamecfg = {"savedgamecfg", "0", true}; -cvar_t saved1 = {"saved1", "0", true}; -cvar_t saved2 = {"saved2", "0", true}; -cvar_t saved3 = {"saved3", "0", true}; -cvar_t saved4 = {"saved4", "0", true}; - -#define MAX_FIELD_LEN 64 -#define GEFV_CACHESIZE 2 - -typedef struct { - ddef_t *pcache; - char field[MAX_FIELD_LEN]; -} gefv_cache; - -static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; - -/* -================= -ED_ClearEdict - -Sets everything to NULL -================= -*/ -void ED_ClearEdict (edict_t *e) -{ - memset (&e->v, 0, progs->entityfields * 4); - e->free = false; -} - -/* -================= -ED_Alloc - -Either finds a free edict, or allocates a new one. -Try to avoid reusing an entity that was recently freed, because it -can cause the client to think the entity morphed into something else -instead of being removed and recreated, which can cause interpolated -angles and bad trails. -================= -*/ -edict_t *ED_Alloc (void) -{ - int i; - edict_t *e; - - for ( i=svs.maxclients+1 ; ifree && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ) - { - ED_ClearEdict (e); - return e; - } - } - - if (i == MAX_EDICTS) - Sys_Error ("ED_Alloc: no free edicts"); - - sv.num_edicts++; - e = EDICT_NUM(i); - ED_ClearEdict (e); - - return e; -} - -/* -================= -ED_Free - -Marks the edict as free -FIXME: walk all entities and NULL out references to this entity -================= -*/ -void ED_Free (edict_t *ed) -{ - SV_UnlinkEdict (ed); // unlink from world bsp - - ed->free = true; - ed->v.model = 0; - ed->v.takedamage = 0; - ed->v.modelindex = 0; - ed->v.colormap = 0; - ed->v.skin = 0; - ed->v.frame = 0; - VectorCopy (vec3_origin, ed->v.origin); - VectorCopy (vec3_origin, ed->v.angles); - ed->v.nextthink = -1; - ed->v.solid = 0; - - ed->freetime = sv.time; -} - -//=========================================================================== - -/* -============ -ED_GlobalAtOfs -============ -*/ -ddef_t *ED_GlobalAtOfs (int ofs) -{ - ddef_t *def; - int i; - - for (i=0 ; inumglobaldefs ; i++) - { - def = &pr_globaldefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* -============ -ED_FieldAtOfs -============ -*/ -ddef_t *ED_FieldAtOfs (int ofs) -{ - ddef_t *def; - int i; - - for (i=0 ; inumfielddefs ; i++) - { - def = &pr_fielddefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; -} - -/* -============ -ED_FindField -============ -*/ -ddef_t *ED_FindField (char *name) -{ - ddef_t *def; - int i; - - for (i=0 ; inumfielddefs ; i++) - { - def = &pr_fielddefs[i]; - if (!strcmp(pr_strings + def->s_name,name) ) - return def; - } - return NULL; -} - - -/* -============ -ED_FindGlobal -============ -*/ -ddef_t *ED_FindGlobal (char *name) -{ - ddef_t *def; - int i; - - for (i=0 ; inumglobaldefs ; i++) - { - def = &pr_globaldefs[i]; - if (!strcmp(pr_strings + def->s_name,name) ) - return def; - } - return NULL; -} - - -/* -============ -ED_FindFunction -============ -*/ -dfunction_t *ED_FindFunction (char *name) -{ - dfunction_t *func; - int i; - - for (i=0 ; inumfunctions ; i++) - { - func = &pr_functions[i]; - if (!strcmp(pr_strings + func->s_name,name) ) - return func; - } - return NULL; -} - - -eval_t *GetEdictFieldValue(edict_t *ed, char *field) -{ - ddef_t *def = NULL; - int i; - static int rep = 0; - - for (i=0 ; iv + def->ofs*4); -} - - -/* -============ -PR_ValueString - -Returns a string describing *data in a type specific manner -============= -*/ -char *PR_ValueString (etype_t type, eval_t *val) -{ - static char line[256]; - ddef_t *def; - dfunction_t *f; - - type &= ~DEF_SAVEGLOBAL; - - switch (type) - { - case ev_string: - sprintf (line, "%s", pr_strings + val->string); - break; - case ev_entity: - sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) ); - break; - case ev_function: - f = pr_functions + val->function; - sprintf (line, "%s()", pr_strings + f->s_name); - break; - case ev_field: - def = ED_FieldAtOfs ( val->_int ); - sprintf (line, ".%s", pr_strings + def->s_name); - break; - case ev_void: - sprintf (line, "void"); - break; - case ev_float: - sprintf (line, "%5.1f", val->_float); - break; - case ev_vector: - sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]); - break; - case ev_pointer: - sprintf (line, "pointer"); - break; - default: - sprintf (line, "bad type %i", type); - break; - } - - return line; -} - -/* -============ -PR_UglyValueString - -Returns a string describing *data in a type specific manner -Easier to parse than PR_ValueString -============= -*/ -char *PR_UglyValueString (etype_t type, eval_t *val) -{ - static char line[256]; - ddef_t *def; - dfunction_t *f; - - type &= ~DEF_SAVEGLOBAL; - - switch (type) - { - case ev_string: - sprintf (line, "%s", pr_strings + val->string); - break; - case ev_entity: - sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); - break; - case ev_function: - f = pr_functions + val->function; - sprintf (line, "%s", pr_strings + f->s_name); - break; - case ev_field: - def = ED_FieldAtOfs ( val->_int ); - sprintf (line, "%s", pr_strings + def->s_name); - break; - case ev_void: - sprintf (line, "void"); - break; - case ev_float: - sprintf (line, "%f", val->_float); - break; - case ev_vector: - sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]); - break; - default: - sprintf (line, "bad type %i", type); - break; - } - - return line; -} - -/* -============ -PR_GlobalString - -Returns a string with a description and the contents of a global, -padded to 20 field width -============ -*/ -char *PR_GlobalString (int ofs) -{ - char *s; - int i; - ddef_t *def; - void *val; - static char line[128]; - - val = (void *)&pr_globals[ofs]; - def = ED_GlobalAtOfs(ofs); - if (!def) - sprintf (line,"%i(???)", ofs); - else - { - s = PR_ValueString (def->type, val); - sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s); - } - - i = strlen(line); - for ( ; i<20 ; i++) - strcat (line," "); - strcat (line," "); - - return line; -} - -char *PR_GlobalStringNoContents (int ofs) -{ - int i; - ddef_t *def; - static char line[128]; - - def = ED_GlobalAtOfs(ofs); - if (!def) - sprintf (line,"%i(???)", ofs); - else - sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name); - - i = strlen(line); - for ( ; i<20 ; i++) - strcat (line," "); - strcat (line," "); - - return line; -} - - -/* -============= -ED_Print - -For debugging -============= -*/ -void ED_Print (edict_t *ed) -{ - int l; - ddef_t *d; - int *v; - int i, j; - char *name; - int type; - - if (ed->free) - { - Con_Printf ("FREE\n"); - return; - } - - Con_Printf("\nEDICT %i:\n", NUM_FOR_EDICT(ed)); - for (i=1 ; inumfielddefs ; i++) - { - d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; - if (name[strlen(name)-2] == '_') - continue; // skip _x, _y, _z vars - - v = (int *)((char *)&ed->v + d->ofs*4); - - // if the value is still all 0, skip the field - type = d->type & ~DEF_SAVEGLOBAL; - - for (j=0 ; jtype, (eval_t *)v)); - } -} - -/* -============= -ED_Write - -For savegames -============= -*/ -void ED_Write (FILE *f, edict_t *ed) -{ - ddef_t *d; - int *v; - int i, j; - char *name; - int type; - - fprintf (f, "{\n"); - - if (ed->free) - { - fprintf (f, "}\n"); - return; - } - - for (i=1 ; inumfielddefs ; i++) - { - d = &pr_fielddefs[i]; - name = pr_strings + d->s_name; - if (name[strlen(name)-2] == '_') - continue; // skip _x, _y, _z vars - - v = (int *)((char *)&ed->v + d->ofs*4); - - // if the value is still all 0, skip the field - type = d->type & ~DEF_SAVEGLOBAL; - for (j=0 ; jtype, (eval_t *)v)); - } - - fprintf (f, "}\n"); -} - -void ED_PrintNum (int ent) -{ - ED_Print (EDICT_NUM(ent)); -} - -/* -============= -ED_PrintEdicts - -For debugging, prints all the entities in the current server -============= -*/ -void ED_PrintEdicts (void) -{ - int i; - - Con_Printf ("%i entities\n", sv.num_edicts); - for (i=0 ; i= sv.num_edicts) - { - Con_Printf("Bad edict number\n"); - return; - } - ED_PrintNum (i); -} - -/* -============= -ED_Count - -For debugging -============= -*/ -void ED_Count (void) -{ - int i; - edict_t *ent; - int active, models, solid, step; - - active = models = solid = step = 0; - for (i=0 ; ifree) - continue; - active++; - if (ent->v.solid) - solid++; - if (ent->v.model) - models++; - if (ent->v.movetype == MOVETYPE_STEP) - step++; - } - - Con_Printf ("num_edicts:%3i\n", sv.num_edicts); - Con_Printf ("active :%3i\n", active); - Con_Printf ("view :%3i\n", models); - Con_Printf ("touch :%3i\n", solid); - Con_Printf ("step :%3i\n", step); - -} - -/* -============================================================================== - - ARCHIVING GLOBALS - -FIXME: need to tag constants, doesn't really work -============================================================================== -*/ - -/* -============= -ED_WriteGlobals -============= -*/ -void ED_WriteGlobals (FILE *f) -{ - ddef_t *def; - int i; - char *name; - int type; - - fprintf (f,"{\n"); - for (i=0 ; inumglobaldefs ; i++) - { - def = &pr_globaldefs[i]; - type = def->type; - if ( !(def->type & DEF_SAVEGLOBAL) ) - continue; - type &= ~DEF_SAVEGLOBAL; - - if (type != ev_string - && type != ev_float - && type != ev_entity) - continue; - - name = pr_strings + def->s_name; - fprintf (f,"\"%s\" ", name); - fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs])); - } - fprintf (f,"}\n"); -} - -/* -============= -ED_ParseGlobals -============= -*/ -void ED_ParseGlobals (char *data) -{ - char keyname[64]; - ddef_t *key; - - while (1) - { - // parse key - data = COM_Parse (data); - if (com_token[0] == '}') - break; - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - strcpy (keyname, com_token); - - // parse value - data = COM_Parse (data); - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - if (com_token[0] == '}') - Sys_Error ("ED_ParseEntity: closing brace without data"); - - key = ED_FindGlobal (keyname); - if (!key) - { - Con_Printf ("'%s' is not a global\n", keyname); - continue; - } - - if (!ED_ParseEpair ((void *)pr_globals, key, com_token)) - Host_Error ("ED_ParseGlobals: parse error"); - } -} - -//============================================================================ - - -/* -============= -ED_NewString -============= -*/ -char *ED_NewString (char *string) -{ - char *new, *new_p; - int i,l; - - l = strlen(string) + 1; - new = Hunk_Alloc (l); - new_p = new; - - for (i=0 ; i< l ; i++) - { - if (string[i] == '\\' && i < l-1) - { - i++; - if (string[i] == 'n') - *new_p++ = '\n'; - else - *new_p++ = '\\'; - } - else - *new_p++ = string[i]; - } - - return new; -} - - -/* -============= -ED_ParseEval - -Can parse either fields or globals -returns false if error -============= -*/ -qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) -{ - int i; - char string[128]; - ddef_t *def; - char *v, *w; - void *d; - dfunction_t *func; - - d = (void *)((int *)base + key->ofs); - - switch (key->type & ~DEF_SAVEGLOBAL) - { - case ev_string: - *(string_t *)d = ED_NewString (s) - pr_strings; - break; - - case ev_float: - *(float *)d = atof (s); - break; - - case ev_vector: - strcpy (string, s); - v = string; - w = string; - for (i=0 ; i<3 ; i++) - { - while (*v && *v != ' ') - v++; - *v = 0; - ((float *)d)[i] = atof (w); - w = v = v+1; - } - break; - - case ev_entity: - *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s))); - break; - - case ev_field: - def = ED_FindField (s); - if (!def) - { - Con_Printf ("Can't find field %s\n", s); - return false; - } - *(int *)d = G_INT(def->ofs); - break; - - case ev_function: - func = ED_FindFunction (s); - if (!func) - { - Con_Printf ("Can't find function %s\n", s); - return false; - } - *(func_t *)d = func - pr_functions; - break; - - default: - break; - } - return true; -} - -/* -==================== -ED_ParseEdict - -Parses an edict out of the given string, returning the new position -ed should be a properly initialized empty edict. -Used for initial level load and for savegames. -==================== -*/ -char *ED_ParseEdict (char *data, edict_t *ent) -{ - ddef_t *key; - qboolean anglehack; - qboolean init; - char keyname[256]; - int n; - - init = false; - -// clear it - if (ent != sv.edicts) // hack - memset (&ent->v, 0, progs->entityfields * 4); - -// go through all the dictionary pairs - while (1) - { - // parse key - data = COM_Parse (data); - if (com_token[0] == '}') - break; - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - -// anglehack is to allow QuakeEd to write single scalar angles -// and allow them to be turned into vectors. (FIXME...) -if (!strcmp(com_token, "angle")) -{ - strcpy (com_token, "angles"); - anglehack = true; -} -else - anglehack = false; - -// FIXME: change light to _light to get rid of this hack -if (!strcmp(com_token, "light")) - strcpy (com_token, "light_lev"); // hack for single light def - - strcpy (keyname, com_token); - - // another hack to fix heynames with trailing spaces - n = strlen(keyname); - while (n && keyname[n-1] == ' ') - { - keyname[n-1] = 0; - n--; - } - - // parse value - data = COM_Parse (data); - if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); - - if (com_token[0] == '}') - Sys_Error ("ED_ParseEntity: closing brace without data"); - - init = true; - -// keynames with a leading underscore are used for utility comments, -// and are immediately discarded by quake - if (keyname[0] == '_') - continue; - - key = ED_FindField (keyname); - if (!key) - { - Con_Printf ("'%s' is not a field\n", keyname); - continue; - } - -if (anglehack) -{ -char temp[32]; -strcpy (temp, com_token); -sprintf (com_token, "0 %s 0", temp); -} - - if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) - Host_Error ("ED_ParseEdict: parse error"); - } - - if (!init) - ent->free = true; - - return data; -} - - -/* -================ -ED_LoadFromFile - -The entities are directly placed in the array, rather than allocated with -ED_Alloc, because otherwise an error loading the map would have entity -number references out of order. - -Creates a server's entity / program execution context by -parsing textual entity definitions out of an ent file. - -Used for both fresh maps and savegame loads. A fresh map would also need -to call ED_CallSpawnFunctions () to let the objects initialize themselves. -================ -*/ -void ED_LoadFromFile (char *data) -{ - edict_t *ent; - int inhibit; - dfunction_t *func; - - ent = NULL; - inhibit = 0; - pr_global_struct->time = sv.time; - -// parse ents - while (1) - { -// parse the opening brace - data = COM_Parse (data); - if (!data) - break; - if (com_token[0] != '{') - Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token); - - if (!ent) - ent = EDICT_NUM(0); - else - ent = ED_Alloc (); - data = ED_ParseEdict (data, ent); - -// remove things from different skill levels or deathmatch - if (deathmatch.value) - { - if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) - { - ED_Free (ent); - inhibit++; - continue; - } - } - else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY)) - || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) - || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) ) - { - ED_Free (ent); - inhibit++; - continue; - } - -// -// immediately call spawn function -// - if (!ent->v.classname) - { - Con_Printf ("No classname for:\n"); - ED_Print (ent); - ED_Free (ent); - continue; - } - - // look for the spawn function - func = ED_FindFunction ( pr_strings + ent->v.classname ); - - if (!func) - { - Con_Printf ("No spawn function for:\n"); - ED_Print (ent); - ED_Free (ent); - continue; - } - - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (func - pr_functions); - } - - Con_DPrintf ("%i entities inhibited\n", inhibit); -} - - -/* -=============== -PR_LoadProgs -=============== -*/ -void PR_LoadProgs (void) -{ - int i; - -// flush the non-C variable lookup cache - for (i=0 ; iversion != PROG_VERSION) - Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); - if (progs->crc != PROGHEADER_CRC) - Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date"); - - pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); - pr_strings = (char *)progs + progs->ofs_strings; - pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); - pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); - pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); - - pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); - pr_globals = (float *)pr_global_struct; - - pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); - -// byte swap the lumps - for (i=0 ; inumstatements ; i++) - { - pr_statements[i].op = LittleShort(pr_statements[i].op); - pr_statements[i].a = LittleShort(pr_statements[i].a); - pr_statements[i].b = LittleShort(pr_statements[i].b); - pr_statements[i].c = LittleShort(pr_statements[i].c); - } - - for (i=0 ; inumfunctions; i++) - { - pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); - pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); - pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); - pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); - pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); - pr_functions[i].locals = LittleLong (pr_functions[i].locals); - } - - for (i=0 ; inumglobaldefs ; i++) - { - pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); - pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); - pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); - } - - for (i=0 ; inumfielddefs ; i++) - { - pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); - if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) - Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); - pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); - } - - for (i=0 ; inumglobals ; i++) - ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); -} - - -/* -=============== -PR_Init -=============== -*/ -void PR_Init (void) -{ - Cmd_AddCommand ("edict", ED_PrintEdict_f); - Cmd_AddCommand ("edicts", ED_PrintEdicts); - Cmd_AddCommand ("edictcount", ED_Count); - Cmd_AddCommand ("profile", PR_Profile_f); - Cvar_RegisterVariable (&nomonsters); - Cvar_RegisterVariable (&gamecfg); - Cvar_RegisterVariable (&scratch1); - Cvar_RegisterVariable (&scratch2); - Cvar_RegisterVariable (&scratch3); - Cvar_RegisterVariable (&scratch4); - Cvar_RegisterVariable (&savedgamecfg); - Cvar_RegisterVariable (&saved1); - Cvar_RegisterVariable (&saved2); - Cvar_RegisterVariable (&saved3); - Cvar_RegisterVariable (&saved4); -} - - - -edict_t *EDICT_NUM(int n) -{ - if (n < 0 || n >= sv.max_edicts) - Sys_Error ("EDICT_NUM: bad number %i", n); - return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size); -} - -int NUM_FOR_EDICT(edict_t *e) -{ - int b; - - b = (byte *)e - (byte *)sv.edicts; - b = b / pr_edict_size; - - if (b < 0 || b >= sv.num_edicts) - Sys_Error ("NUM_FOR_EDICT: bad pointer"); - return b; -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_edict.c -- entity dictionary + +#include "quakedef.h" + +dprograms_t *progs; +dfunction_t *pr_functions; +char *pr_strings; +ddef_t *pr_fielddefs; +ddef_t *pr_globaldefs; +dstatement_t *pr_statements; +globalvars_t *pr_global_struct; +float *pr_globals; // same as pr_global_struct +int pr_edict_size; // in bytes + +unsigned short pr_crc; + +int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}; + +ddef_t *ED_FieldAtOfs (int ofs); +qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); + +cvar_t nomonsters = {"nomonsters", "0"}; +cvar_t gamecfg = {"gamecfg", "0"}; +cvar_t scratch1 = {"scratch1", "0"}; +cvar_t scratch2 = {"scratch2", "0"}; +cvar_t scratch3 = {"scratch3", "0"}; +cvar_t scratch4 = {"scratch4", "0"}; +cvar_t savedgamecfg = {"savedgamecfg", "0", true}; +cvar_t saved1 = {"saved1", "0", true}; +cvar_t saved2 = {"saved2", "0", true}; +cvar_t saved3 = {"saved3", "0", true}; +cvar_t saved4 = {"saved4", "0", true}; + +#define MAX_FIELD_LEN 64 +#define GEFV_CACHESIZE 2 + +typedef struct { + ddef_t *pcache; + char field[MAX_FIELD_LEN]; +} gefv_cache; + +static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; + +/* +================= +ED_ClearEdict + +Sets everything to NULL +================= +*/ +void ED_ClearEdict (edict_t *e) +{ + memset (&e->v, 0, progs->entityfields * 4); + e->free = false; +} + +/* +================= +ED_Alloc + +Either finds a free edict, or allocates a new one. +Try to avoid reusing an entity that was recently freed, because it +can cause the client to think the entity morphed into something else +instead of being removed and recreated, which can cause interpolated +angles and bad trails. +================= +*/ +edict_t *ED_Alloc (void) +{ + int i; + edict_t *e; + + for ( i=svs.maxclients+1 ; ifree && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ) + { + ED_ClearEdict (e); + return e; + } + } + + if (i == MAX_EDICTS) + Sys_Error ("ED_Alloc: no free edicts"); + + sv.num_edicts++; + e = EDICT_NUM(i); + ED_ClearEdict (e); + + return e; +} + +/* +================= +ED_Free + +Marks the edict as free +FIXME: walk all entities and NULL out references to this entity +================= +*/ +void ED_Free (edict_t *ed) +{ + SV_UnlinkEdict (ed); // unlink from world bsp + + ed->free = true; + ed->v.model = 0; + ed->v.takedamage = 0; + ed->v.modelindex = 0; + ed->v.colormap = 0; + ed->v.skin = 0; + ed->v.frame = 0; + VectorCopy (vec3_origin, ed->v.origin); + VectorCopy (vec3_origin, ed->v.angles); + ed->v.nextthink = -1; + ed->v.solid = 0; + + ed->freetime = sv.time; +} + +//=========================================================================== + +/* +============ +ED_GlobalAtOfs +============ +*/ +ddef_t *ED_GlobalAtOfs (int ofs) +{ + ddef_t *def; + int i; + + for (i=0 ; inumglobaldefs ; i++) + { + def = &pr_globaldefs[i]; + if (def->ofs == ofs) + return def; + } + return NULL; +} + +/* +============ +ED_FieldAtOfs +============ +*/ +ddef_t *ED_FieldAtOfs (int ofs) +{ + ddef_t *def; + int i; + + for (i=0 ; inumfielddefs ; i++) + { + def = &pr_fielddefs[i]; + if (def->ofs == ofs) + return def; + } + return NULL; +} + +/* +============ +ED_FindField +============ +*/ +ddef_t *ED_FindField (char *name) +{ + ddef_t *def; + int i; + + for (i=0 ; inumfielddefs ; i++) + { + def = &pr_fielddefs[i]; + if (!strcmp(pr_strings + def->s_name,name) ) + return def; + } + return NULL; +} + + +/* +============ +ED_FindGlobal +============ +*/ +ddef_t *ED_FindGlobal (char *name) +{ + ddef_t *def; + int i; + + for (i=0 ; inumglobaldefs ; i++) + { + def = &pr_globaldefs[i]; + if (!strcmp(pr_strings + def->s_name,name) ) + return def; + } + return NULL; +} + + +/* +============ +ED_FindFunction +============ +*/ +dfunction_t *ED_FindFunction (char *name) +{ + dfunction_t *func; + int i; + + for (i=0 ; inumfunctions ; i++) + { + func = &pr_functions[i]; + if (!strcmp(pr_strings + func->s_name,name) ) + return func; + } + return NULL; +} + + +eval_t *GetEdictFieldValue(edict_t *ed, char *field) +{ + ddef_t *def = NULL; + int i; + static int rep = 0; + + for (i=0 ; iv + def->ofs*4); +} + + +/* +============ +PR_ValueString + +Returns a string describing *data in a type specific manner +============= +*/ +char *PR_ValueString (etype_t type, eval_t *val) +{ + static char line[256]; + ddef_t *def; + dfunction_t *f; + + type &= ~DEF_SAVEGLOBAL; + + switch (type) + { + case ev_string: + sprintf (line, "%s", pr_strings + val->string); + break; + case ev_entity: + sprintf (line, "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)) ); + break; + case ev_function: + f = pr_functions + val->function; + sprintf (line, "%s()", pr_strings + f->s_name); + break; + case ev_field: + def = ED_FieldAtOfs ( val->_int ); + sprintf (line, ".%s", pr_strings + def->s_name); + break; + case ev_void: + sprintf (line, "void"); + break; + case ev_float: + sprintf (line, "%5.1f", val->_float); + break; + case ev_vector: + sprintf (line, "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]); + break; + case ev_pointer: + sprintf (line, "pointer"); + break; + default: + sprintf (line, "bad type %i", type); + break; + } + + return line; +} + +/* +============ +PR_UglyValueString + +Returns a string describing *data in a type specific manner +Easier to parse than PR_ValueString +============= +*/ +char *PR_UglyValueString (etype_t type, eval_t *val) +{ + static char line[256]; + ddef_t *def; + dfunction_t *f; + + type &= ~DEF_SAVEGLOBAL; + + switch (type) + { + case ev_string: + sprintf (line, "%s", pr_strings + val->string); + break; + case ev_entity: + sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); + break; + case ev_function: + f = pr_functions + val->function; + sprintf (line, "%s", pr_strings + f->s_name); + break; + case ev_field: + def = ED_FieldAtOfs ( val->_int ); + sprintf (line, "%s", pr_strings + def->s_name); + break; + case ev_void: + sprintf (line, "void"); + break; + case ev_float: + sprintf (line, "%f", val->_float); + break; + case ev_vector: + sprintf (line, "%f %f %f", val->vector[0], val->vector[1], val->vector[2]); + break; + default: + sprintf (line, "bad type %i", type); + break; + } + + return line; +} + +/* +============ +PR_GlobalString + +Returns a string with a description and the contents of a global, +padded to 20 field width +============ +*/ +char *PR_GlobalString (int ofs) +{ + char *s; + int i; + ddef_t *def; + void *val; + static char line[128]; + + val = (void *)&pr_globals[ofs]; + def = ED_GlobalAtOfs(ofs); + if (!def) + sprintf (line,"%i(???)", ofs); + else + { + s = PR_ValueString (def->type, val); + sprintf (line,"%i(%s)%s", ofs, pr_strings + def->s_name, s); + } + + i = strlen(line); + for ( ; i<20 ; i++) + strcat (line," "); + strcat (line," "); + + return line; +} + +char *PR_GlobalStringNoContents (int ofs) +{ + int i; + ddef_t *def; + static char line[128]; + + def = ED_GlobalAtOfs(ofs); + if (!def) + sprintf (line,"%i(???)", ofs); + else + sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name); + + i = strlen(line); + for ( ; i<20 ; i++) + strcat (line," "); + strcat (line," "); + + return line; +} + + +/* +============= +ED_Print + +For debugging +============= +*/ +void ED_Print (edict_t *ed) +{ + int l; + ddef_t *d; + int *v; + int i, j; + char *name; + int type; + + if (ed->free) + { + Con_Printf ("FREE\n"); + return; + } + + Con_Printf("\nEDICT %i:\n", NUM_FOR_EDICT(ed)); + for (i=1 ; inumfielddefs ; i++) + { + d = &pr_fielddefs[i]; + name = pr_strings + d->s_name; + if (name[strlen(name)-2] == '_') + continue; // skip _x, _y, _z vars + + v = (int *)((char *)&ed->v + d->ofs*4); + + // if the value is still all 0, skip the field + type = d->type & ~DEF_SAVEGLOBAL; + + for (j=0 ; jtype, (eval_t *)v)); + } +} + +/* +============= +ED_Write + +For savegames +============= +*/ +void ED_Write (FILE *f, edict_t *ed) +{ + ddef_t *d; + int *v; + int i, j; + char *name; + int type; + + fprintf (f, "{\n"); + + if (ed->free) + { + fprintf (f, "}\n"); + return; + } + + for (i=1 ; inumfielddefs ; i++) + { + d = &pr_fielddefs[i]; + name = pr_strings + d->s_name; + if (name[strlen(name)-2] == '_') + continue; // skip _x, _y, _z vars + + v = (int *)((char *)&ed->v + d->ofs*4); + + // if the value is still all 0, skip the field + type = d->type & ~DEF_SAVEGLOBAL; + for (j=0 ; jtype, (eval_t *)v)); + } + + fprintf (f, "}\n"); +} + +void ED_PrintNum (int ent) +{ + ED_Print (EDICT_NUM(ent)); +} + +/* +============= +ED_PrintEdicts + +For debugging, prints all the entities in the current server +============= +*/ +void ED_PrintEdicts (void) +{ + int i; + + Con_Printf ("%i entities\n", sv.num_edicts); + for (i=0 ; i= sv.num_edicts) + { + Con_Printf("Bad edict number\n"); + return; + } + ED_PrintNum (i); +} + +/* +============= +ED_Count + +For debugging +============= +*/ +void ED_Count (void) +{ + int i; + edict_t *ent; + int active, models, solid, step; + + active = models = solid = step = 0; + for (i=0 ; ifree) + continue; + active++; + if (ent->v.solid) + solid++; + if (ent->v.model) + models++; + if (ent->v.movetype == MOVETYPE_STEP) + step++; + } + + Con_Printf ("num_edicts:%3i\n", sv.num_edicts); + Con_Printf ("active :%3i\n", active); + Con_Printf ("view :%3i\n", models); + Con_Printf ("touch :%3i\n", solid); + Con_Printf ("step :%3i\n", step); + +} + +/* +============================================================================== + + ARCHIVING GLOBALS + +FIXME: need to tag constants, doesn't really work +============================================================================== +*/ + +/* +============= +ED_WriteGlobals +============= +*/ +void ED_WriteGlobals (FILE *f) +{ + ddef_t *def; + int i; + char *name; + int type; + + fprintf (f,"{\n"); + for (i=0 ; inumglobaldefs ; i++) + { + def = &pr_globaldefs[i]; + type = def->type; + if ( !(def->type & DEF_SAVEGLOBAL) ) + continue; + type &= ~DEF_SAVEGLOBAL; + + if (type != ev_string + && type != ev_float + && type != ev_entity) + continue; + + name = pr_strings + def->s_name; + fprintf (f,"\"%s\" ", name); + fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs])); + } + fprintf (f,"}\n"); +} + +/* +============= +ED_ParseGlobals +============= +*/ +void ED_ParseGlobals (char *data) +{ + char keyname[64]; + ddef_t *key; + + while (1) + { + // parse key + data = COM_Parse (data); + if (com_token[0] == '}') + break; + if (!data) + Sys_Error ("ED_ParseEntity: EOF without closing brace"); + + strcpy (keyname, com_token); + + // parse value + data = COM_Parse (data); + if (!data) + Sys_Error ("ED_ParseEntity: EOF without closing brace"); + + if (com_token[0] == '}') + Sys_Error ("ED_ParseEntity: closing brace without data"); + + key = ED_FindGlobal (keyname); + if (!key) + { + Con_Printf ("'%s' is not a global\n", keyname); + continue; + } + + if (!ED_ParseEpair ((void *)pr_globals, key, com_token)) + Host_Error ("ED_ParseGlobals: parse error"); + } +} + +//============================================================================ + + +/* +============= +ED_NewString +============= +*/ +char *ED_NewString (char *string) +{ + char *new, *new_p; + int i,l; + + l = strlen(string) + 1; + new = Hunk_Alloc (l); + new_p = new; + + for (i=0 ; i< l ; i++) + { + if (string[i] == '\\' && i < l-1) + { + i++; + if (string[i] == 'n') + *new_p++ = '\n'; + else + *new_p++ = '\\'; + } + else + *new_p++ = string[i]; + } + + return new; +} + + +/* +============= +ED_ParseEval + +Can parse either fields or globals +returns false if error +============= +*/ +qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) +{ + int i; + char string[128]; + ddef_t *def; + char *v, *w; + void *d; + dfunction_t *func; + + d = (void *)((int *)base + key->ofs); + + switch (key->type & ~DEF_SAVEGLOBAL) + { + case ev_string: + *(string_t *)d = ED_NewString (s) - pr_strings; + break; + + case ev_float: + *(float *)d = atof (s); + break; + + case ev_vector: + strcpy (string, s); + v = string; + w = string; + for (i=0 ; i<3 ; i++) + { + while (*v && *v != ' ') + v++; + *v = 0; + ((float *)d)[i] = atof (w); + w = v = v+1; + } + break; + + case ev_entity: + *(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s))); + break; + + case ev_field: + def = ED_FindField (s); + if (!def) + { + Con_Printf ("Can't find field %s\n", s); + return false; + } + *(int *)d = G_INT(def->ofs); + break; + + case ev_function: + func = ED_FindFunction (s); + if (!func) + { + Con_Printf ("Can't find function %s\n", s); + return false; + } + *(func_t *)d = func - pr_functions; + break; + + default: + break; + } + return true; +} + +/* +==================== +ED_ParseEdict + +Parses an edict out of the given string, returning the new position +ed should be a properly initialized empty edict. +Used for initial level load and for savegames. +==================== +*/ +char *ED_ParseEdict (char *data, edict_t *ent) +{ + ddef_t *key; + qboolean anglehack; + qboolean init; + char keyname[256]; + int n; + + init = false; + +// clear it + if (ent != sv.edicts) // hack + memset (&ent->v, 0, progs->entityfields * 4); + +// go through all the dictionary pairs + while (1) + { + // parse key + data = COM_Parse (data); + if (com_token[0] == '}') + break; + if (!data) + Sys_Error ("ED_ParseEntity: EOF without closing brace"); + +// anglehack is to allow QuakeEd to write single scalar angles +// and allow them to be turned into vectors. (FIXME...) +if (!strcmp(com_token, "angle")) +{ + strcpy (com_token, "angles"); + anglehack = true; +} +else + anglehack = false; + +// FIXME: change light to _light to get rid of this hack +if (!strcmp(com_token, "light")) + strcpy (com_token, "light_lev"); // hack for single light def + + strcpy (keyname, com_token); + + // another hack to fix heynames with trailing spaces + n = strlen(keyname); + while (n && keyname[n-1] == ' ') + { + keyname[n-1] = 0; + n--; + } + + // parse value + data = COM_Parse (data); + if (!data) + Sys_Error ("ED_ParseEntity: EOF without closing brace"); + + if (com_token[0] == '}') + Sys_Error ("ED_ParseEntity: closing brace without data"); + + init = true; + +// keynames with a leading underscore are used for utility comments, +// and are immediately discarded by quake + if (keyname[0] == '_') + continue; + + key = ED_FindField (keyname); + if (!key) + { + Con_Printf ("'%s' is not a field\n", keyname); + continue; + } + +if (anglehack) +{ +char temp[32]; +strcpy (temp, com_token); +sprintf (com_token, "0 %s 0", temp); +} + + if (!ED_ParseEpair ((void *)&ent->v, key, com_token)) + Host_Error ("ED_ParseEdict: parse error"); + } + + if (!init) + ent->free = true; + + return data; +} + + +/* +================ +ED_LoadFromFile + +The entities are directly placed in the array, rather than allocated with +ED_Alloc, because otherwise an error loading the map would have entity +number references out of order. + +Creates a server's entity / program execution context by +parsing textual entity definitions out of an ent file. + +Used for both fresh maps and savegame loads. A fresh map would also need +to call ED_CallSpawnFunctions () to let the objects initialize themselves. +================ +*/ +void ED_LoadFromFile (char *data) +{ + edict_t *ent; + int inhibit; + dfunction_t *func; + + ent = NULL; + inhibit = 0; + pr_global_struct->time = sv.time; + +// parse ents + while (1) + { +// parse the opening brace + data = COM_Parse (data); + if (!data) + break; + if (com_token[0] != '{') + Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token); + + if (!ent) + ent = EDICT_NUM(0); + else + ent = ED_Alloc (); + data = ED_ParseEdict (data, ent); + +// remove things from different skill levels or deathmatch + if (deathmatch.value) + { + if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) + { + ED_Free (ent); + inhibit++; + continue; + } + } + else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY)) + || (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) + || (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) ) + { + ED_Free (ent); + inhibit++; + continue; + } + +// +// immediately call spawn function +// + if (!ent->v.classname) + { + Con_Printf ("No classname for:\n"); + ED_Print (ent); + ED_Free (ent); + continue; + } + + // look for the spawn function + func = ED_FindFunction ( pr_strings + ent->v.classname ); + + if (!func) + { + Con_Printf ("No spawn function for:\n"); + ED_Print (ent); + ED_Free (ent); + continue; + } + + pr_global_struct->self = EDICT_TO_PROG(ent); + PR_ExecuteProgram (func - pr_functions); + } + + Con_DPrintf ("%i entities inhibited\n", inhibit); +} + + +/* +=============== +PR_LoadProgs +=============== +*/ +void PR_LoadProgs (void) +{ + int i; + +// flush the non-C variable lookup cache + for (i=0 ; iversion != PROG_VERSION) + Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); + if (progs->crc != PROGHEADER_CRC) + Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date"); + + pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); + pr_strings = (char *)progs + progs->ofs_strings; + pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); + pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); + pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); + + pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); + pr_globals = (float *)pr_global_struct; + + pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); + +// byte swap the lumps + for (i=0 ; inumstatements ; i++) + { + pr_statements[i].op = LittleShort(pr_statements[i].op); + pr_statements[i].a = LittleShort(pr_statements[i].a); + pr_statements[i].b = LittleShort(pr_statements[i].b); + pr_statements[i].c = LittleShort(pr_statements[i].c); + } + + for (i=0 ; inumfunctions; i++) + { + pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); + pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); + pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); + pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); + pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); + pr_functions[i].locals = LittleLong (pr_functions[i].locals); + } + + for (i=0 ; inumglobaldefs ; i++) + { + pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); + pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); + pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); + } + + for (i=0 ; inumfielddefs ; i++) + { + pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); + if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) + Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); + pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); + pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); + } + + for (i=0 ; inumglobals ; i++) + ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); +} + + +/* +=============== +PR_Init +=============== +*/ +void PR_Init (void) +{ + Cmd_AddCommand ("edict", ED_PrintEdict_f); + Cmd_AddCommand ("edicts", ED_PrintEdicts); + Cmd_AddCommand ("edictcount", ED_Count); + Cmd_AddCommand ("profile", PR_Profile_f); + Cvar_RegisterVariable (&nomonsters); + Cvar_RegisterVariable (&gamecfg); + Cvar_RegisterVariable (&scratch1); + Cvar_RegisterVariable (&scratch2); + Cvar_RegisterVariable (&scratch3); + Cvar_RegisterVariable (&scratch4); + Cvar_RegisterVariable (&savedgamecfg); + Cvar_RegisterVariable (&saved1); + Cvar_RegisterVariable (&saved2); + Cvar_RegisterVariable (&saved3); + Cvar_RegisterVariable (&saved4); +} + + + +edict_t *EDICT_NUM(int n) +{ + if (n < 0 || n >= sv.max_edicts) + Sys_Error ("EDICT_NUM: bad number %i", n); + return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size); +} + +int NUM_FOR_EDICT(edict_t *e) +{ + int b; + + b = (byte *)e - (byte *)sv.edicts; + b = b / pr_edict_size; + + if (b < 0 || b >= sv.num_edicts) + Sys_Error ("NUM_FOR_EDICT: bad pointer"); + return b; +} diff --git a/WinQuake/pr_exec.c b/WinQuake/pr_exec.c index 4f2aa36..3fa0d29 100644 --- a/WinQuake/pr_exec.c +++ b/WinQuake/pr_exec.c @@ -1,668 +1,668 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - - -/* - -*/ - -typedef struct -{ - int s; - dfunction_t *f; -} prstack_t; - -#define MAX_STACK_DEPTH 32 -prstack_t pr_stack[MAX_STACK_DEPTH]; -int pr_depth; - -#define LOCALSTACK_SIZE 2048 -int localstack[LOCALSTACK_SIZE]; -int localstack_used; - - -qboolean pr_trace; -dfunction_t *pr_xfunction; -int pr_xstatement; - - -int pr_argc; - -char *pr_opnames[] = -{ -"DONE", - -"MUL_F", -"MUL_V", -"MUL_FV", -"MUL_VF", - -"DIV", - -"ADD_F", -"ADD_V", - -"SUB_F", -"SUB_V", - -"EQ_F", -"EQ_V", -"EQ_S", -"EQ_E", -"EQ_FNC", - -"NE_F", -"NE_V", -"NE_S", -"NE_E", -"NE_FNC", - -"LE", -"GE", -"LT", -"GT", - -"INDIRECT", -"INDIRECT", -"INDIRECT", -"INDIRECT", -"INDIRECT", -"INDIRECT", - -"ADDRESS", - -"STORE_F", -"STORE_V", -"STORE_S", -"STORE_ENT", -"STORE_FLD", -"STORE_FNC", - -"STOREP_F", -"STOREP_V", -"STOREP_S", -"STOREP_ENT", -"STOREP_FLD", -"STOREP_FNC", - -"RETURN", - -"NOT_F", -"NOT_V", -"NOT_S", -"NOT_ENT", -"NOT_FNC", - -"IF", -"IFNOT", - -"CALL0", -"CALL1", -"CALL2", -"CALL3", -"CALL4", -"CALL5", -"CALL6", -"CALL7", -"CALL8", - -"STATE", - -"GOTO", - -"AND", -"OR", - -"BITAND", -"BITOR" -}; - -char *PR_GlobalString (int ofs); -char *PR_GlobalStringNoContents (int ofs); - - -//============================================================================= - -/* -================= -PR_PrintStatement -================= -*/ -void PR_PrintStatement (dstatement_t *s) -{ - int i; - - if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0])) - { - Con_Printf ("%s ", pr_opnames[s->op]); - i = strlen(pr_opnames[s->op]); - for ( ; i<10 ; i++) - Con_Printf (" "); - } - - if (s->op == OP_IF || s->op == OP_IFNOT) - Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b); - else if (s->op == OP_GOTO) - { - Con_Printf ("branch %i",s->a); - } - else if ( (unsigned)(s->op - OP_STORE_F) < 6) - { - Con_Printf ("%s",PR_GlobalString(s->a)); - Con_Printf ("%s", PR_GlobalStringNoContents(s->b)); - } - else - { - if (s->a) - Con_Printf ("%s",PR_GlobalString(s->a)); - if (s->b) - Con_Printf ("%s",PR_GlobalString(s->b)); - if (s->c) - Con_Printf ("%s", PR_GlobalStringNoContents(s->c)); - } - Con_Printf ("\n"); -} - -/* -============ -PR_StackTrace -============ -*/ -void PR_StackTrace (void) -{ - dfunction_t *f; - int i; - - if (pr_depth == 0) - { - Con_Printf ("\n"); - return; - } - - pr_stack[pr_depth].f = pr_xfunction; - for (i=pr_depth ; i>=0 ; i--) - { - f = pr_stack[i].f; - - if (!f) - { - Con_Printf ("\n"); - } - else - Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name); - } -} - - -/* -============ -PR_Profile_f - -============ -*/ -void PR_Profile_f (void) -{ - dfunction_t *f, *best; - int max; - int num; - int i; - - num = 0; - do - { - max = 0; - best = NULL; - for (i=0 ; inumfunctions ; i++) - { - f = &pr_functions[i]; - if (f->profile > max) - { - max = f->profile; - best = f; - } - } - if (best) - { - if (num < 10) - Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name); - num++; - best->profile = 0; - } - } while (best); -} - - -/* -============ -PR_RunError - -Aborts the currently executing function -============ -*/ -void PR_RunError (char *error, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr,error); - vsprintf (string,error,argptr); - va_end (argptr); - - PR_PrintStatement (pr_statements + pr_xstatement); - PR_StackTrace (); - Con_Printf ("%s\n", string); - - pr_depth = 0; // dump the stack so host_error can shutdown functions - - Host_Error ("Program error"); -} - -/* -============================================================================ -PR_ExecuteProgram - -The interpretation main loop -============================================================================ -*/ - -/* -==================== -PR_EnterFunction - -Returns the new program statement counter -==================== -*/ -int PR_EnterFunction (dfunction_t *f) -{ - int i, j, c, o; - - pr_stack[pr_depth].s = pr_xstatement; - pr_stack[pr_depth].f = pr_xfunction; - pr_depth++; - if (pr_depth >= MAX_STACK_DEPTH) - PR_RunError ("stack overflow"); - -// save off any locals that the new function steps on - c = f->locals; - if (localstack_used + c > LOCALSTACK_SIZE) - PR_RunError ("PR_ExecuteProgram: locals stack overflow\n"); - - for (i=0 ; i < c ; i++) - localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; - localstack_used += c; - -// copy parameters - o = f->parm_start; - for (i=0 ; inumparms ; i++) - { - for (j=0 ; jparm_size[i] ; j++) - { - ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j]; - o++; - } - } - - pr_xfunction = f; - return f->first_statement - 1; // offset the s++ -} - -/* -==================== -PR_LeaveFunction -==================== -*/ -int PR_LeaveFunction (void) -{ - int i, c; - - if (pr_depth <= 0) - Sys_Error ("prog stack underflow"); - -// restore locals from the stack - c = pr_xfunction->locals; - localstack_used -= c; - if (localstack_used < 0) - PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); - - for (i=0 ; i < c ; i++) - ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i]; - -// up stack - pr_depth--; - pr_xfunction = pr_stack[pr_depth].f; - return pr_stack[pr_depth].s; -} - - -/* -==================== -PR_ExecuteProgram -==================== -*/ -void PR_ExecuteProgram (func_t fnum) -{ - eval_t *a, *b, *c; - int s; - dstatement_t *st; - dfunction_t *f, *newf; - int runaway; - int i; - edict_t *ed; - int exitdepth; - eval_t *ptr; - - if (!fnum || fnum >= progs->numfunctions) - { - if (pr_global_struct->self) - ED_Print (PROG_TO_EDICT(pr_global_struct->self)); - Host_Error ("PR_ExecuteProgram: NULL function"); - } - - f = &pr_functions[fnum]; - - runaway = 100000; - pr_trace = false; - -// make a stack frame - exitdepth = pr_depth; - - s = PR_EnterFunction (f); - -while (1) -{ - s++; // next statement - - st = &pr_statements[s]; - a = (eval_t *)&pr_globals[st->a]; - b = (eval_t *)&pr_globals[st->b]; - c = (eval_t *)&pr_globals[st->c]; - - if (!--runaway) - PR_RunError ("runaway loop error"); - - pr_xfunction->profile++; - pr_xstatement = s; - - if (pr_trace) - PR_PrintStatement (st); - - switch (st->op) - { - case OP_ADD_F: - c->_float = a->_float + b->_float; - break; - case OP_ADD_V: - c->vector[0] = a->vector[0] + b->vector[0]; - c->vector[1] = a->vector[1] + b->vector[1]; - c->vector[2] = a->vector[2] + b->vector[2]; - break; - - case OP_SUB_F: - c->_float = a->_float - b->_float; - break; - case OP_SUB_V: - c->vector[0] = a->vector[0] - b->vector[0]; - c->vector[1] = a->vector[1] - b->vector[1]; - c->vector[2] = a->vector[2] - b->vector[2]; - break; - - case OP_MUL_F: - c->_float = a->_float * b->_float; - break; - case OP_MUL_V: - c->_float = a->vector[0]*b->vector[0] - + a->vector[1]*b->vector[1] - + a->vector[2]*b->vector[2]; - break; - case OP_MUL_FV: - c->vector[0] = a->_float * b->vector[0]; - c->vector[1] = a->_float * b->vector[1]; - c->vector[2] = a->_float * b->vector[2]; - break; - case OP_MUL_VF: - c->vector[0] = b->_float * a->vector[0]; - c->vector[1] = b->_float * a->vector[1]; - c->vector[2] = b->_float * a->vector[2]; - break; - - case OP_DIV_F: - c->_float = a->_float / b->_float; - break; - - case OP_BITAND: - c->_float = (int)a->_float & (int)b->_float; - break; - - case OP_BITOR: - c->_float = (int)a->_float | (int)b->_float; - break; - - - case OP_GE: - c->_float = a->_float >= b->_float; - break; - case OP_LE: - c->_float = a->_float <= b->_float; - break; - case OP_GT: - c->_float = a->_float > b->_float; - break; - case OP_LT: - c->_float = a->_float < b->_float; - break; - case OP_AND: - c->_float = a->_float && b->_float; - break; - case OP_OR: - c->_float = a->_float || b->_float; - break; - - case OP_NOT_F: - c->_float = !a->_float; - break; - case OP_NOT_V: - c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; - break; - case OP_NOT_S: - c->_float = !a->string || !pr_strings[a->string]; - break; - case OP_NOT_FNC: - c->_float = !a->function; - break; - case OP_NOT_ENT: - c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); - break; - - case OP_EQ_F: - c->_float = a->_float == b->_float; - break; - case OP_EQ_V: - c->_float = (a->vector[0] == b->vector[0]) && - (a->vector[1] == b->vector[1]) && - (a->vector[2] == b->vector[2]); - break; - case OP_EQ_S: - c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); - break; - case OP_EQ_E: - c->_float = a->_int == b->_int; - break; - case OP_EQ_FNC: - c->_float = a->function == b->function; - break; - - - case OP_NE_F: - c->_float = a->_float != b->_float; - break; - case OP_NE_V: - c->_float = (a->vector[0] != b->vector[0]) || - (a->vector[1] != b->vector[1]) || - (a->vector[2] != b->vector[2]); - break; - case OP_NE_S: - c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); - break; - case OP_NE_E: - c->_float = a->_int != b->_int; - break; - case OP_NE_FNC: - c->_float = a->function != b->function; - break; - -//================== - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - b->_int = a->_int; - break; - case OP_STORE_V: - b->vector[0] = a->vector[0]; - b->vector[1] = a->vector[1]; - b->vector[2] = a->vector[2]; - break; - - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - ptr = (eval_t *)((byte *)sv.edicts + b->_int); - ptr->_int = a->_int; - break; - case OP_STOREP_V: - ptr = (eval_t *)((byte *)sv.edicts + b->_int); - ptr->vector[0] = a->vector[0]; - ptr->vector[1] = a->vector[1]; - ptr->vector[2] = a->vector[2]; - break; - - case OP_ADDRESS: - ed = PROG_TO_EDICT(a->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - if (ed == (edict_t *)sv.edicts && sv.state == ss_active) - PR_RunError ("assignment to world entity"); - c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; - break; - - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - ed = PROG_TO_EDICT(a->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - a = (eval_t *)((int *)&ed->v + b->_int); - c->_int = a->_int; - break; - - case OP_LOAD_V: - ed = PROG_TO_EDICT(a->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - a = (eval_t *)((int *)&ed->v + b->_int); - c->vector[0] = a->vector[0]; - c->vector[1] = a->vector[1]; - c->vector[2] = a->vector[2]; - break; - -//================== - - case OP_IFNOT: - if (!a->_int) - s += st->b - 1; // offset the s++ - break; - - case OP_IF: - if (a->_int) - s += st->b - 1; // offset the s++ - break; - - case OP_GOTO: - s += st->a - 1; // offset the s++ - break; - - case OP_CALL0: - case OP_CALL1: - case OP_CALL2: - case OP_CALL3: - case OP_CALL4: - case OP_CALL5: - case OP_CALL6: - case OP_CALL7: - case OP_CALL8: - pr_argc = st->op - OP_CALL0; - if (!a->function) - PR_RunError ("NULL function"); - - newf = &pr_functions[a->function]; - - if (newf->first_statement < 0) - { // negative statements are built in functions - i = -newf->first_statement; - if (i >= pr_numbuiltins) - PR_RunError ("Bad builtin call number"); - pr_builtins[i] (); - break; - } - - s = PR_EnterFunction (newf); - break; - - case OP_DONE: - case OP_RETURN: - pr_globals[OFS_RETURN] = pr_globals[st->a]; - pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; - pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; - - s = PR_LeaveFunction (); - if (pr_depth == exitdepth) - return; // all done - break; - - case OP_STATE: - ed = PROG_TO_EDICT(pr_global_struct->self); -#ifdef FPS_20 - ed->v.nextthink = pr_global_struct->time + 0.05; -#else - ed->v.nextthink = pr_global_struct->time + 0.1; -#endif - if (a->_float != ed->v.frame) - { - ed->v.frame = a->_float; - } - ed->v.think = b->function; - break; - - default: - PR_RunError ("Bad opcode %i", st->op); - } -} - -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + + +/* + +*/ + +typedef struct +{ + int s; + dfunction_t *f; +} prstack_t; + +#define MAX_STACK_DEPTH 32 +prstack_t pr_stack[MAX_STACK_DEPTH]; +int pr_depth; + +#define LOCALSTACK_SIZE 2048 +int localstack[LOCALSTACK_SIZE]; +int localstack_used; + + +qboolean pr_trace; +dfunction_t *pr_xfunction; +int pr_xstatement; + + +int pr_argc; + +char *pr_opnames[] = +{ +"DONE", + +"MUL_F", +"MUL_V", +"MUL_FV", +"MUL_VF", + +"DIV", + +"ADD_F", +"ADD_V", + +"SUB_F", +"SUB_V", + +"EQ_F", +"EQ_V", +"EQ_S", +"EQ_E", +"EQ_FNC", + +"NE_F", +"NE_V", +"NE_S", +"NE_E", +"NE_FNC", + +"LE", +"GE", +"LT", +"GT", + +"INDIRECT", +"INDIRECT", +"INDIRECT", +"INDIRECT", +"INDIRECT", +"INDIRECT", + +"ADDRESS", + +"STORE_F", +"STORE_V", +"STORE_S", +"STORE_ENT", +"STORE_FLD", +"STORE_FNC", + +"STOREP_F", +"STOREP_V", +"STOREP_S", +"STOREP_ENT", +"STOREP_FLD", +"STOREP_FNC", + +"RETURN", + +"NOT_F", +"NOT_V", +"NOT_S", +"NOT_ENT", +"NOT_FNC", + +"IF", +"IFNOT", + +"CALL0", +"CALL1", +"CALL2", +"CALL3", +"CALL4", +"CALL5", +"CALL6", +"CALL7", +"CALL8", + +"STATE", + +"GOTO", + +"AND", +"OR", + +"BITAND", +"BITOR" +}; + +char *PR_GlobalString (int ofs); +char *PR_GlobalStringNoContents (int ofs); + + +//============================================================================= + +/* +================= +PR_PrintStatement +================= +*/ +void PR_PrintStatement (dstatement_t *s) +{ + int i; + + if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0])) + { + Con_Printf ("%s ", pr_opnames[s->op]); + i = strlen(pr_opnames[s->op]); + for ( ; i<10 ; i++) + Con_Printf (" "); + } + + if (s->op == OP_IF || s->op == OP_IFNOT) + Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b); + else if (s->op == OP_GOTO) + { + Con_Printf ("branch %i",s->a); + } + else if ( (unsigned)(s->op - OP_STORE_F) < 6) + { + Con_Printf ("%s",PR_GlobalString(s->a)); + Con_Printf ("%s", PR_GlobalStringNoContents(s->b)); + } + else + { + if (s->a) + Con_Printf ("%s",PR_GlobalString(s->a)); + if (s->b) + Con_Printf ("%s",PR_GlobalString(s->b)); + if (s->c) + Con_Printf ("%s", PR_GlobalStringNoContents(s->c)); + } + Con_Printf ("\n"); +} + +/* +============ +PR_StackTrace +============ +*/ +void PR_StackTrace (void) +{ + dfunction_t *f; + int i; + + if (pr_depth == 0) + { + Con_Printf ("\n"); + return; + } + + pr_stack[pr_depth].f = pr_xfunction; + for (i=pr_depth ; i>=0 ; i--) + { + f = pr_stack[i].f; + + if (!f) + { + Con_Printf ("\n"); + } + else + Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name); + } +} + + +/* +============ +PR_Profile_f + +============ +*/ +void PR_Profile_f (void) +{ + dfunction_t *f, *best; + int max; + int num; + int i; + + num = 0; + do + { + max = 0; + best = NULL; + for (i=0 ; inumfunctions ; i++) + { + f = &pr_functions[i]; + if (f->profile > max) + { + max = f->profile; + best = f; + } + } + if (best) + { + if (num < 10) + Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name); + num++; + best->profile = 0; + } + } while (best); +} + + +/* +============ +PR_RunError + +Aborts the currently executing function +============ +*/ +void PR_RunError (char *error, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + + PR_PrintStatement (pr_statements + pr_xstatement); + PR_StackTrace (); + Con_Printf ("%s\n", string); + + pr_depth = 0; // dump the stack so host_error can shutdown functions + + Host_Error ("Program error"); +} + +/* +============================================================================ +PR_ExecuteProgram + +The interpretation main loop +============================================================================ +*/ + +/* +==================== +PR_EnterFunction + +Returns the new program statement counter +==================== +*/ +int PR_EnterFunction (dfunction_t *f) +{ + int i, j, c, o; + + pr_stack[pr_depth].s = pr_xstatement; + pr_stack[pr_depth].f = pr_xfunction; + pr_depth++; + if (pr_depth >= MAX_STACK_DEPTH) + PR_RunError ("stack overflow"); + +// save off any locals that the new function steps on + c = f->locals; + if (localstack_used + c > LOCALSTACK_SIZE) + PR_RunError ("PR_ExecuteProgram: locals stack overflow\n"); + + for (i=0 ; i < c ; i++) + localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i]; + localstack_used += c; + +// copy parameters + o = f->parm_start; + for (i=0 ; inumparms ; i++) + { + for (j=0 ; jparm_size[i] ; j++) + { + ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j]; + o++; + } + } + + pr_xfunction = f; + return f->first_statement - 1; // offset the s++ +} + +/* +==================== +PR_LeaveFunction +==================== +*/ +int PR_LeaveFunction (void) +{ + int i, c; + + if (pr_depth <= 0) + Sys_Error ("prog stack underflow"); + +// restore locals from the stack + c = pr_xfunction->locals; + localstack_used -= c; + if (localstack_used < 0) + PR_RunError ("PR_ExecuteProgram: locals stack underflow\n"); + + for (i=0 ; i < c ; i++) + ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i]; + +// up stack + pr_depth--; + pr_xfunction = pr_stack[pr_depth].f; + return pr_stack[pr_depth].s; +} + + +/* +==================== +PR_ExecuteProgram +==================== +*/ +void PR_ExecuteProgram (func_t fnum) +{ + eval_t *a, *b, *c; + int s; + dstatement_t *st; + dfunction_t *f, *newf; + int runaway; + int i; + edict_t *ed; + int exitdepth; + eval_t *ptr; + + if (!fnum || fnum >= progs->numfunctions) + { + if (pr_global_struct->self) + ED_Print (PROG_TO_EDICT(pr_global_struct->self)); + Host_Error ("PR_ExecuteProgram: NULL function"); + } + + f = &pr_functions[fnum]; + + runaway = 100000; + pr_trace = false; + +// make a stack frame + exitdepth = pr_depth; + + s = PR_EnterFunction (f); + +while (1) +{ + s++; // next statement + + st = &pr_statements[s]; + a = (eval_t *)&pr_globals[st->a]; + b = (eval_t *)&pr_globals[st->b]; + c = (eval_t *)&pr_globals[st->c]; + + if (!--runaway) + PR_RunError ("runaway loop error"); + + pr_xfunction->profile++; + pr_xstatement = s; + + if (pr_trace) + PR_PrintStatement (st); + + switch (st->op) + { + case OP_ADD_F: + c->_float = a->_float + b->_float; + break; + case OP_ADD_V: + c->vector[0] = a->vector[0] + b->vector[0]; + c->vector[1] = a->vector[1] + b->vector[1]; + c->vector[2] = a->vector[2] + b->vector[2]; + break; + + case OP_SUB_F: + c->_float = a->_float - b->_float; + break; + case OP_SUB_V: + c->vector[0] = a->vector[0] - b->vector[0]; + c->vector[1] = a->vector[1] - b->vector[1]; + c->vector[2] = a->vector[2] - b->vector[2]; + break; + + case OP_MUL_F: + c->_float = a->_float * b->_float; + break; + case OP_MUL_V: + c->_float = a->vector[0]*b->vector[0] + + a->vector[1]*b->vector[1] + + a->vector[2]*b->vector[2]; + break; + case OP_MUL_FV: + c->vector[0] = a->_float * b->vector[0]; + c->vector[1] = a->_float * b->vector[1]; + c->vector[2] = a->_float * b->vector[2]; + break; + case OP_MUL_VF: + c->vector[0] = b->_float * a->vector[0]; + c->vector[1] = b->_float * a->vector[1]; + c->vector[2] = b->_float * a->vector[2]; + break; + + case OP_DIV_F: + c->_float = a->_float / b->_float; + break; + + case OP_BITAND: + c->_float = (int)a->_float & (int)b->_float; + break; + + case OP_BITOR: + c->_float = (int)a->_float | (int)b->_float; + break; + + + case OP_GE: + c->_float = a->_float >= b->_float; + break; + case OP_LE: + c->_float = a->_float <= b->_float; + break; + case OP_GT: + c->_float = a->_float > b->_float; + break; + case OP_LT: + c->_float = a->_float < b->_float; + break; + case OP_AND: + c->_float = a->_float && b->_float; + break; + case OP_OR: + c->_float = a->_float || b->_float; + break; + + case OP_NOT_F: + c->_float = !a->_float; + break; + case OP_NOT_V: + c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; + break; + case OP_NOT_S: + c->_float = !a->string || !pr_strings[a->string]; + break; + case OP_NOT_FNC: + c->_float = !a->function; + break; + case OP_NOT_ENT: + c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); + break; + + case OP_EQ_F: + c->_float = a->_float == b->_float; + break; + case OP_EQ_V: + c->_float = (a->vector[0] == b->vector[0]) && + (a->vector[1] == b->vector[1]) && + (a->vector[2] == b->vector[2]); + break; + case OP_EQ_S: + c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); + break; + case OP_EQ_E: + c->_float = a->_int == b->_int; + break; + case OP_EQ_FNC: + c->_float = a->function == b->function; + break; + + + case OP_NE_F: + c->_float = a->_float != b->_float; + break; + case OP_NE_V: + c->_float = (a->vector[0] != b->vector[0]) || + (a->vector[1] != b->vector[1]) || + (a->vector[2] != b->vector[2]); + break; + case OP_NE_S: + c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); + break; + case OP_NE_E: + c->_float = a->_int != b->_int; + break; + case OP_NE_FNC: + c->_float = a->function != b->function; + break; + +//================== + case OP_STORE_F: + case OP_STORE_ENT: + case OP_STORE_FLD: // integers + case OP_STORE_S: + case OP_STORE_FNC: // pointers + b->_int = a->_int; + break; + case OP_STORE_V: + b->vector[0] = a->vector[0]; + b->vector[1] = a->vector[1]; + b->vector[2] = a->vector[2]; + break; + + case OP_STOREP_F: + case OP_STOREP_ENT: + case OP_STOREP_FLD: // integers + case OP_STOREP_S: + case OP_STOREP_FNC: // pointers + ptr = (eval_t *)((byte *)sv.edicts + b->_int); + ptr->_int = a->_int; + break; + case OP_STOREP_V: + ptr = (eval_t *)((byte *)sv.edicts + b->_int); + ptr->vector[0] = a->vector[0]; + ptr->vector[1] = a->vector[1]; + ptr->vector[2] = a->vector[2]; + break; + + case OP_ADDRESS: + ed = PROG_TO_EDICT(a->edict); +#ifdef PARANOID + NUM_FOR_EDICT(ed); // make sure it's in range +#endif + if (ed == (edict_t *)sv.edicts && sv.state == ss_active) + PR_RunError ("assignment to world entity"); + c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; + break; + + case OP_LOAD_F: + case OP_LOAD_FLD: + case OP_LOAD_ENT: + case OP_LOAD_S: + case OP_LOAD_FNC: + ed = PROG_TO_EDICT(a->edict); +#ifdef PARANOID + NUM_FOR_EDICT(ed); // make sure it's in range +#endif + a = (eval_t *)((int *)&ed->v + b->_int); + c->_int = a->_int; + break; + + case OP_LOAD_V: + ed = PROG_TO_EDICT(a->edict); +#ifdef PARANOID + NUM_FOR_EDICT(ed); // make sure it's in range +#endif + a = (eval_t *)((int *)&ed->v + b->_int); + c->vector[0] = a->vector[0]; + c->vector[1] = a->vector[1]; + c->vector[2] = a->vector[2]; + break; + +//================== + + case OP_IFNOT: + if (!a->_int) + s += st->b - 1; // offset the s++ + break; + + case OP_IF: + if (a->_int) + s += st->b - 1; // offset the s++ + break; + + case OP_GOTO: + s += st->a - 1; // offset the s++ + break; + + case OP_CALL0: + case OP_CALL1: + case OP_CALL2: + case OP_CALL3: + case OP_CALL4: + case OP_CALL5: + case OP_CALL6: + case OP_CALL7: + case OP_CALL8: + pr_argc = st->op - OP_CALL0; + if (!a->function) + PR_RunError ("NULL function"); + + newf = &pr_functions[a->function]; + + if (newf->first_statement < 0) + { // negative statements are built in functions + i = -newf->first_statement; + if (i >= pr_numbuiltins) + PR_RunError ("Bad builtin call number"); + pr_builtins[i] (); + break; + } + + s = PR_EnterFunction (newf); + break; + + case OP_DONE: + case OP_RETURN: + pr_globals[OFS_RETURN] = pr_globals[st->a]; + pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; + pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; + + s = PR_LeaveFunction (); + if (pr_depth == exitdepth) + return; // all done + break; + + case OP_STATE: + ed = PROG_TO_EDICT(pr_global_struct->self); +#ifdef FPS_20 + ed->v.nextthink = pr_global_struct->time + 0.05; +#else + ed->v.nextthink = pr_global_struct->time + 0.1; +#endif + if (a->_float != ed->v.frame) + { + ed->v.frame = a->_float; + } + ed->v.think = b->function; + break; + + default: + PR_RunError ("Bad opcode %i", st->op); + } +} + +} diff --git a/WinQuake/progdefs.h b/WinQuake/progdefs.h index db86de1..6681b44 100644 --- a/WinQuake/progdefs.h +++ b/WinQuake/progdefs.h @@ -1,24 +1,24 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifdef QUAKE2 -#include "progdefs.q2" -#else -#include "progdefs.q1" -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifdef QUAKE2 +#include "progdefs.q2" +#else +#include "progdefs.q1" +#endif diff --git a/WinQuake/progdefs.q1 b/WinQuake/progdefs.q1 index eb15c45..c976cf8 100644 --- a/WinQuake/progdefs.q1 +++ b/WinQuake/progdefs.q1 @@ -1,143 +1,143 @@ - -/* file generated by qcc, do not modify */ - -typedef struct -{ int pad[28]; - int self; - int other; - int world; - float time; - float frametime; - float force_retouch; - string_t mapname; - float deathmatch; - float coop; - float teamplay; - float serverflags; - float total_secrets; - float total_monsters; - float found_secrets; - float killed_monsters; - float parm1; - float parm2; - float parm3; - float parm4; - float parm5; - float parm6; - float parm7; - float parm8; - float parm9; - float parm10; - float parm11; - float parm12; - float parm13; - float parm14; - float parm15; - float parm16; - vec3_t v_forward; - vec3_t v_up; - vec3_t v_right; - float trace_allsolid; - float trace_startsolid; - float trace_fraction; - vec3_t trace_endpos; - vec3_t trace_plane_normal; - float trace_plane_dist; - int trace_ent; - float trace_inopen; - float trace_inwater; - int msg_entity; - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; -} globalvars_t; - -typedef struct -{ - float modelindex; - vec3_t absmin; - vec3_t absmax; - float ltime; - float movetype; - float solid; - vec3_t origin; - vec3_t oldorigin; - vec3_t velocity; - vec3_t angles; - vec3_t avelocity; - vec3_t punchangle; - string_t classname; - string_t model; - float frame; - float skin; - float effects; - vec3_t mins; - vec3_t maxs; - vec3_t size; - func_t touch; - func_t use; - func_t think; - func_t blocked; - float nextthink; - int groundentity; - float health; - float frags; - float weapon; - string_t weaponmodel; - float weaponframe; - float currentammo; - float ammo_shells; - float ammo_nails; - float ammo_rockets; - float ammo_cells; - float items; - float takedamage; - int chain; - float deadflag; - vec3_t view_ofs; - float button0; - float button1; - float button2; - float impulse; - float fixangle; - vec3_t v_angle; - float idealpitch; - string_t netname; - int enemy; - float flags; - float colormap; - float team; - float max_health; - float teleport_time; - float armortype; - float armorvalue; - float waterlevel; - float watertype; - float ideal_yaw; - float yaw_speed; - int aiment; - int goalentity; - float spawnflags; - string_t target; - string_t targetname; - float dmg_take; - float dmg_save; - int dmg_inflictor; - int owner; - vec3_t movedir; - string_t message; - float sounds; - string_t noise; - string_t noise1; - string_t noise2; - string_t noise3; -} entvars_t; - -#define PROGHEADER_CRC 5927 + +/* file generated by qcc, do not modify */ + +typedef struct +{ int pad[28]; + int self; + int other; + int world; + float time; + float frametime; + float force_retouch; + string_t mapname; + float deathmatch; + float coop; + float teamplay; + float serverflags; + float total_secrets; + float total_monsters; + float found_secrets; + float killed_monsters; + float parm1; + float parm2; + float parm3; + float parm4; + float parm5; + float parm6; + float parm7; + float parm8; + float parm9; + float parm10; + float parm11; + float parm12; + float parm13; + float parm14; + float parm15; + float parm16; + vec3_t v_forward; + vec3_t v_up; + vec3_t v_right; + float trace_allsolid; + float trace_startsolid; + float trace_fraction; + vec3_t trace_endpos; + vec3_t trace_plane_normal; + float trace_plane_dist; + int trace_ent; + float trace_inopen; + float trace_inwater; + int msg_entity; + func_t main; + func_t StartFrame; + func_t PlayerPreThink; + func_t PlayerPostThink; + func_t ClientKill; + func_t ClientConnect; + func_t PutClientInServer; + func_t ClientDisconnect; + func_t SetNewParms; + func_t SetChangeParms; +} globalvars_t; + +typedef struct +{ + float modelindex; + vec3_t absmin; + vec3_t absmax; + float ltime; + float movetype; + float solid; + vec3_t origin; + vec3_t oldorigin; + vec3_t velocity; + vec3_t angles; + vec3_t avelocity; + vec3_t punchangle; + string_t classname; + string_t model; + float frame; + float skin; + float effects; + vec3_t mins; + vec3_t maxs; + vec3_t size; + func_t touch; + func_t use; + func_t think; + func_t blocked; + float nextthink; + int groundentity; + float health; + float frags; + float weapon; + string_t weaponmodel; + float weaponframe; + float currentammo; + float ammo_shells; + float ammo_nails; + float ammo_rockets; + float ammo_cells; + float items; + float takedamage; + int chain; + float deadflag; + vec3_t view_ofs; + float button0; + float button1; + float button2; + float impulse; + float fixangle; + vec3_t v_angle; + float idealpitch; + string_t netname; + int enemy; + float flags; + float colormap; + float team; + float max_health; + float teleport_time; + float armortype; + float armorvalue; + float waterlevel; + float watertype; + float ideal_yaw; + float yaw_speed; + int aiment; + int goalentity; + float spawnflags; + string_t target; + string_t targetname; + float dmg_take; + float dmg_save; + int dmg_inflictor; + int owner; + vec3_t movedir; + string_t message; + float sounds; + string_t noise; + string_t noise1; + string_t noise2; + string_t noise3; +} entvars_t; + +#define PROGHEADER_CRC 5927 diff --git a/WinQuake/progdefs.q2 b/WinQuake/progdefs.q2 index dc7f3be..cff3d3d 100644 --- a/WinQuake/progdefs.q2 +++ b/WinQuake/progdefs.q2 @@ -1,158 +1,158 @@ - -/* file generated by qcc, do not modify */ - -typedef struct -{ int pad[28]; - int self; - int other; - int world; - float time; - float frametime; - float force_retouch; - string_t mapname; - string_t startspot; - float deathmatch; - float coop; - float teamplay; - float serverflags; - float total_secrets; - float total_monsters; - float found_secrets; - float killed_monsters; - float parm1; - float parm2; - float parm3; - float parm4; - float parm5; - float parm6; - float parm7; - float parm8; - float parm9; - float parm10; - float parm11; - float parm12; - float parm13; - float parm14; - float parm15; - float parm16; - vec3_t v_forward; - vec3_t v_up; - vec3_t v_right; - float trace_allsolid; - float trace_startsolid; - float trace_fraction; - vec3_t trace_endpos; - vec3_t trace_plane_normal; - float trace_plane_dist; - int trace_ent; - float trace_inopen; - float trace_inwater; - int msg_entity; - string_t null; - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; -} globalvars_t; - -typedef struct -{ - float modelindex; - vec3_t absmin; - vec3_t absmax; - float ltime; - float movetype; - float solid; - vec3_t origin; - vec3_t oldorigin; - vec3_t velocity; - vec3_t angles; - vec3_t avelocity; - vec3_t basevelocity; - vec3_t punchangle; - string_t classname; - string_t model; - float frame; - float skin; - float effects; - float drawPercent; - float gravity; - float mass; - float light_level; - vec3_t mins; - vec3_t maxs; - vec3_t size; - func_t touch; - func_t use; - func_t think; - func_t blocked; - float nextthink; - int groundentity; - float health; - float frags; - float weapon; - string_t weaponmodel; - float weaponframe; - float currentammo; - float ammo_shells; - float ammo_nails; - float ammo_rockets; - float ammo_cells; - float items; - float items2; - float takedamage; - int chain; - float deadflag; - vec3_t view_ofs; - float button0; - float button1; - float button2; - float impulse; - float fixangle; - vec3_t v_angle; - float idealpitch; - float pitch_speed; - string_t netname; - int enemy; - float flags; - float colormap; - float team; - float max_health; - float teleport_time; - float armortype; - float armorvalue; - float waterlevel; - float watertype; - float ideal_yaw; - float yaw_speed; - int aiment; - int goalentity; - float spawnflags; - string_t target; - string_t targetname; - float dmg_take; - float dmg_save; - int dmg_inflictor; - int owner; - vec3_t movedir; - string_t message; - float sounds; - string_t noise; - string_t noise1; - string_t noise2; - string_t noise3; - float dmg; - float dmgtime; - float air_finished; - float pain_finished; - float radsuit_finished; - float speed; -} entvars_t; - -#define PROGHEADER_CRC 31586 + +/* file generated by qcc, do not modify */ + +typedef struct +{ int pad[28]; + int self; + int other; + int world; + float time; + float frametime; + float force_retouch; + string_t mapname; + string_t startspot; + float deathmatch; + float coop; + float teamplay; + float serverflags; + float total_secrets; + float total_monsters; + float found_secrets; + float killed_monsters; + float parm1; + float parm2; + float parm3; + float parm4; + float parm5; + float parm6; + float parm7; + float parm8; + float parm9; + float parm10; + float parm11; + float parm12; + float parm13; + float parm14; + float parm15; + float parm16; + vec3_t v_forward; + vec3_t v_up; + vec3_t v_right; + float trace_allsolid; + float trace_startsolid; + float trace_fraction; + vec3_t trace_endpos; + vec3_t trace_plane_normal; + float trace_plane_dist; + int trace_ent; + float trace_inopen; + float trace_inwater; + int msg_entity; + string_t null; + func_t main; + func_t StartFrame; + func_t PlayerPreThink; + func_t PlayerPostThink; + func_t ClientKill; + func_t ClientConnect; + func_t PutClientInServer; + func_t ClientDisconnect; + func_t SetNewParms; + func_t SetChangeParms; +} globalvars_t; + +typedef struct +{ + float modelindex; + vec3_t absmin; + vec3_t absmax; + float ltime; + float movetype; + float solid; + vec3_t origin; + vec3_t oldorigin; + vec3_t velocity; + vec3_t angles; + vec3_t avelocity; + vec3_t basevelocity; + vec3_t punchangle; + string_t classname; + string_t model; + float frame; + float skin; + float effects; + float drawPercent; + float gravity; + float mass; + float light_level; + vec3_t mins; + vec3_t maxs; + vec3_t size; + func_t touch; + func_t use; + func_t think; + func_t blocked; + float nextthink; + int groundentity; + float health; + float frags; + float weapon; + string_t weaponmodel; + float weaponframe; + float currentammo; + float ammo_shells; + float ammo_nails; + float ammo_rockets; + float ammo_cells; + float items; + float items2; + float takedamage; + int chain; + float deadflag; + vec3_t view_ofs; + float button0; + float button1; + float button2; + float impulse; + float fixangle; + vec3_t v_angle; + float idealpitch; + float pitch_speed; + string_t netname; + int enemy; + float flags; + float colormap; + float team; + float max_health; + float teleport_time; + float armortype; + float armorvalue; + float waterlevel; + float watertype; + float ideal_yaw; + float yaw_speed; + int aiment; + int goalentity; + float spawnflags; + string_t target; + string_t targetname; + float dmg_take; + float dmg_save; + int dmg_inflictor; + int owner; + vec3_t movedir; + string_t message; + float sounds; + string_t noise; + string_t noise1; + string_t noise2; + string_t noise3; + float dmg; + float dmgtime; + float air_finished; + float pain_finished; + float radsuit_finished; + float speed; +} entvars_t; + +#define PROGHEADER_CRC 31586 diff --git a/WinQuake/progs.h b/WinQuake/progs.h index 6d3aa8a..e2a05f0 100644 --- a/WinQuake/progs.h +++ b/WinQuake/progs.h @@ -1,134 +1,134 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "pr_comp.h" // defs shared with qcc -#include "progdefs.h" // generated by program cdefs - -typedef union eval_s -{ - string_t string; - float _float; - float vector[3]; - func_t function; - int _int; - int edict; -} eval_t; - -#define MAX_ENT_LEAFS 16 -typedef struct edict_s -{ - qboolean free; - link_t area; // linked to a division node or leaf - - int num_leafs; - short leafnums[MAX_ENT_LEAFS]; - - entity_state_t baseline; - - float freetime; // sv.time when the object was freed - entvars_t v; // C exported fields from progs -// other fields from progs come immediately after -} edict_t; -#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) - -//============================================================================ - -extern dprograms_t *progs; -extern dfunction_t *pr_functions; -extern char *pr_strings; -extern ddef_t *pr_globaldefs; -extern ddef_t *pr_fielddefs; -extern dstatement_t *pr_statements; -extern globalvars_t *pr_global_struct; -extern float *pr_globals; // same as pr_global_struct - -extern int pr_edict_size; // in bytes - -//============================================================================ - -void PR_Init (void); - -void PR_ExecuteProgram (func_t fnum); -void PR_LoadProgs (void); - -void PR_Profile_f (void); - -edict_t *ED_Alloc (void); -void ED_Free (edict_t *ed); - -char *ED_NewString (char *string); -// returns a copy of the string allocated from the server's string heap - -void ED_Print (edict_t *ed); -void ED_Write (FILE *f, edict_t *ed); -char *ED_ParseEdict (char *data, edict_t *ent); - -void ED_WriteGlobals (FILE *f); -void ED_ParseGlobals (char *data); - -void ED_LoadFromFile (char *data); - -//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size)) -//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size) - -edict_t *EDICT_NUM(int n); -int NUM_FOR_EDICT(edict_t *e); - -#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size)) - -#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts) -#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e)) - -//============================================================================ - -#define G_FLOAT(o) (pr_globals[o]) -#define G_INT(o) (*(int *)&pr_globals[o]) -#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o])) -#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o)) -#define G_VECTOR(o) (&pr_globals[o]) -#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o]) -#define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) - -#define E_FLOAT(e,o) (((float*)&e->v)[o]) -#define E_INT(e,o) (*(int *)&((float*)&e->v)[o]) -#define E_VECTOR(e,o) (&((float*)&e->v)[o]) -#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o]) - -extern int type_size[8]; - -typedef void (*builtin_t) (void); -extern builtin_t *pr_builtins; -extern int pr_numbuiltins; - -extern int pr_argc; - -extern qboolean pr_trace; -extern dfunction_t *pr_xfunction; -extern int pr_xstatement; - -extern unsigned short pr_crc; - -void PR_RunError (char *error, ...); - -void ED_PrintEdicts (void); -void ED_PrintNum (int ent); - -eval_t *GetEdictFieldValue(edict_t *ed, char *field); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "pr_comp.h" // defs shared with qcc +#include "progdefs.h" // generated by program cdefs + +typedef union eval_s +{ + string_t string; + float _float; + float vector[3]; + func_t function; + int _int; + int edict; +} eval_t; + +#define MAX_ENT_LEAFS 16 +typedef struct edict_s +{ + qboolean free; + link_t area; // linked to a division node or leaf + + int num_leafs; + short leafnums[MAX_ENT_LEAFS]; + + entity_state_t baseline; + + float freetime; // sv.time when the object was freed + entvars_t v; // C exported fields from progs +// other fields from progs come immediately after +} edict_t; +#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) + +//============================================================================ + +extern dprograms_t *progs; +extern dfunction_t *pr_functions; +extern char *pr_strings; +extern ddef_t *pr_globaldefs; +extern ddef_t *pr_fielddefs; +extern dstatement_t *pr_statements; +extern globalvars_t *pr_global_struct; +extern float *pr_globals; // same as pr_global_struct + +extern int pr_edict_size; // in bytes + +//============================================================================ + +void PR_Init (void); + +void PR_ExecuteProgram (func_t fnum); +void PR_LoadProgs (void); + +void PR_Profile_f (void); + +edict_t *ED_Alloc (void); +void ED_Free (edict_t *ed); + +char *ED_NewString (char *string); +// returns a copy of the string allocated from the server's string heap + +void ED_Print (edict_t *ed); +void ED_Write (FILE *f, edict_t *ed); +char *ED_ParseEdict (char *data, edict_t *ent); + +void ED_WriteGlobals (FILE *f); +void ED_ParseGlobals (char *data); + +void ED_LoadFromFile (char *data); + +//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size)) +//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size) + +edict_t *EDICT_NUM(int n); +int NUM_FOR_EDICT(edict_t *e); + +#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size)) + +#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts) +#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e)) + +//============================================================================ + +#define G_FLOAT(o) (pr_globals[o]) +#define G_INT(o) (*(int *)&pr_globals[o]) +#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o])) +#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o)) +#define G_VECTOR(o) (&pr_globals[o]) +#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o]) +#define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) + +#define E_FLOAT(e,o) (((float*)&e->v)[o]) +#define E_INT(e,o) (*(int *)&((float*)&e->v)[o]) +#define E_VECTOR(e,o) (&((float*)&e->v)[o]) +#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o]) + +extern int type_size[8]; + +typedef void (*builtin_t) (void); +extern builtin_t *pr_builtins; +extern int pr_numbuiltins; + +extern int pr_argc; + +extern qboolean pr_trace; +extern dfunction_t *pr_xfunction; +extern int pr_xstatement; + +extern unsigned short pr_crc; + +void PR_RunError (char *error, ...); + +void ED_PrintEdicts (void); +void ED_PrintNum (int ent); + +eval_t *GetEdictFieldValue(edict_t *ed, char *field); + diff --git a/WinQuake/protocol.h b/WinQuake/protocol.h index 01780f8..ec3e58a 100644 --- a/WinQuake/protocol.h +++ b/WinQuake/protocol.h @@ -1,167 +1,167 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// protocol.h -- communications protocols - -#define PROTOCOL_VERSION 15 - -// if the high bit of the servercmd is set, the low bits are fast update flags: -#define U_MOREBITS (1<<0) -#define U_ORIGIN1 (1<<1) -#define U_ORIGIN2 (1<<2) -#define U_ORIGIN3 (1<<3) -#define U_ANGLE2 (1<<4) -#define U_NOLERP (1<<5) // don't interpolate movement -#define U_FRAME (1<<6) -#define U_SIGNAL (1<<7) // just differentiates from other updates - -// svc_update can pass all of the fast update bits, plus more -#define U_ANGLE1 (1<<8) -#define U_ANGLE3 (1<<9) -#define U_MODEL (1<<10) -#define U_COLORMAP (1<<11) -#define U_SKIN (1<<12) -#define U_EFFECTS (1<<13) -#define U_LONGENTITY (1<<14) - - -#define SU_VIEWHEIGHT (1<<0) -#define SU_IDEALPITCH (1<<1) -#define SU_PUNCH1 (1<<2) -#define SU_PUNCH2 (1<<3) -#define SU_PUNCH3 (1<<4) -#define SU_VELOCITY1 (1<<5) -#define SU_VELOCITY2 (1<<6) -#define SU_VELOCITY3 (1<<7) -//define SU_AIMENT (1<<8) AVAILABLE BIT -#define SU_ITEMS (1<<9) -#define SU_ONGROUND (1<<10) // no data follows, the bit is it -#define SU_INWATER (1<<11) // no data follows, the bit is it -#define SU_WEAPONFRAME (1<<12) -#define SU_ARMOR (1<<13) -#define SU_WEAPON (1<<14) - -// a sound with no channel is a local only sound -#define SND_VOLUME (1<<0) // a byte -#define SND_ATTENUATION (1<<1) // a byte -#define SND_LOOPING (1<<2) // a long - - -// defaults for clientinfo messages -#define DEFAULT_VIEWHEIGHT 22 - - -// game types sent by serverinfo -// these determine which intermission screen plays -#define GAME_COOP 0 -#define GAME_DEATHMATCH 1 - -//================== -// note that there are some defs.qc that mirror to these numbers -// also related to svc_strings[] in cl_parse -//================== - -// -// server to client -// -#define svc_bad 0 -#define svc_nop 1 -#define svc_disconnect 2 -#define svc_updatestat 3 // [byte] [long] -#define svc_version 4 // [long] server version -#define svc_setview 5 // [short] entity number -#define svc_sound 6 // -#define svc_time 7 // [float] server time -#define svc_print 8 // [string] null terminated string -#define svc_stufftext 9 // [string] stuffed into client's console buffer - // the string should be \n terminated -#define svc_setangle 10 // [angle3] set the view angle to this absolute value - -#define svc_serverinfo 11 // [long] version - // [string] signon string - // [string]..[0]model cache - // [string]...[0]sounds cache -#define svc_lightstyle 12 // [byte] [string] -#define svc_updatename 13 // [byte] [string] -#define svc_updatefrags 14 // [byte] [short] -#define svc_clientdata 15 // -#define svc_stopsound 16 // -#define svc_updatecolors 17 // [byte] [byte] -#define svc_particle 18 // [vec3] -#define svc_damage 19 - -#define svc_spawnstatic 20 -// svc_spawnbinary 21 -#define svc_spawnbaseline 22 - -#define svc_temp_entity 23 - -#define svc_setpause 24 // [byte] on / off -#define svc_signonnum 25 // [byte] used for the signon sequence - -#define svc_centerprint 26 // [string] to put in center of the screen - -#define svc_killedmonster 27 -#define svc_foundsecret 28 - -#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten - -#define svc_intermission 30 // [string] music -#define svc_finale 31 // [string] music [string] text - -#define svc_cdtrack 32 // [byte] track [byte] looptrack -#define svc_sellscreen 33 - -#define svc_cutscene 34 - -// -// client to server -// -#define clc_bad 0 -#define clc_nop 1 -#define clc_disconnect 2 -#define clc_move 3 // [usercmd_t] -#define clc_stringcmd 4 // [string] message - - -// -// temp entity events -// -#define TE_SPIKE 0 -#define TE_SUPERSPIKE 1 -#define TE_GUNSHOT 2 -#define TE_EXPLOSION 3 -#define TE_TAREXPLOSION 4 -#define TE_LIGHTNING1 5 -#define TE_LIGHTNING2 6 -#define TE_WIZSPIKE 7 -#define TE_KNIGHTSPIKE 8 -#define TE_LIGHTNING3 9 -#define TE_LAVASPLASH 10 -#define TE_TELEPORT 11 -#define TE_EXPLOSION2 12 - -// PGM 01/21/97 -#define TE_BEAM 13 -// PGM 01/21/97 - -#ifdef QUAKE2 -#define TE_IMPLOSION 14 -#define TE_RAILTRAIL 15 -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// protocol.h -- communications protocols + +#define PROTOCOL_VERSION 15 + +// if the high bit of the servercmd is set, the low bits are fast update flags: +#define U_MOREBITS (1<<0) +#define U_ORIGIN1 (1<<1) +#define U_ORIGIN2 (1<<2) +#define U_ORIGIN3 (1<<3) +#define U_ANGLE2 (1<<4) +#define U_NOLERP (1<<5) // don't interpolate movement +#define U_FRAME (1<<6) +#define U_SIGNAL (1<<7) // just differentiates from other updates + +// svc_update can pass all of the fast update bits, plus more +#define U_ANGLE1 (1<<8) +#define U_ANGLE3 (1<<9) +#define U_MODEL (1<<10) +#define U_COLORMAP (1<<11) +#define U_SKIN (1<<12) +#define U_EFFECTS (1<<13) +#define U_LONGENTITY (1<<14) + + +#define SU_VIEWHEIGHT (1<<0) +#define SU_IDEALPITCH (1<<1) +#define SU_PUNCH1 (1<<2) +#define SU_PUNCH2 (1<<3) +#define SU_PUNCH3 (1<<4) +#define SU_VELOCITY1 (1<<5) +#define SU_VELOCITY2 (1<<6) +#define SU_VELOCITY3 (1<<7) +//define SU_AIMENT (1<<8) AVAILABLE BIT +#define SU_ITEMS (1<<9) +#define SU_ONGROUND (1<<10) // no data follows, the bit is it +#define SU_INWATER (1<<11) // no data follows, the bit is it +#define SU_WEAPONFRAME (1<<12) +#define SU_ARMOR (1<<13) +#define SU_WEAPON (1<<14) + +// a sound with no channel is a local only sound +#define SND_VOLUME (1<<0) // a byte +#define SND_ATTENUATION (1<<1) // a byte +#define SND_LOOPING (1<<2) // a long + + +// defaults for clientinfo messages +#define DEFAULT_VIEWHEIGHT 22 + + +// game types sent by serverinfo +// these determine which intermission screen plays +#define GAME_COOP 0 +#define GAME_DEATHMATCH 1 + +//================== +// note that there are some defs.qc that mirror to these numbers +// also related to svc_strings[] in cl_parse +//================== + +// +// server to client +// +#define svc_bad 0 +#define svc_nop 1 +#define svc_disconnect 2 +#define svc_updatestat 3 // [byte] [long] +#define svc_version 4 // [long] server version +#define svc_setview 5 // [short] entity number +#define svc_sound 6 // +#define svc_time 7 // [float] server time +#define svc_print 8 // [string] null terminated string +#define svc_stufftext 9 // [string] stuffed into client's console buffer + // the string should be \n terminated +#define svc_setangle 10 // [angle3] set the view angle to this absolute value + +#define svc_serverinfo 11 // [long] version + // [string] signon string + // [string]..[0]model cache + // [string]...[0]sounds cache +#define svc_lightstyle 12 // [byte] [string] +#define svc_updatename 13 // [byte] [string] +#define svc_updatefrags 14 // [byte] [short] +#define svc_clientdata 15 // +#define svc_stopsound 16 // +#define svc_updatecolors 17 // [byte] [byte] +#define svc_particle 18 // [vec3] +#define svc_damage 19 + +#define svc_spawnstatic 20 +// svc_spawnbinary 21 +#define svc_spawnbaseline 22 + +#define svc_temp_entity 23 + +#define svc_setpause 24 // [byte] on / off +#define svc_signonnum 25 // [byte] used for the signon sequence + +#define svc_centerprint 26 // [string] to put in center of the screen + +#define svc_killedmonster 27 +#define svc_foundsecret 28 + +#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten + +#define svc_intermission 30 // [string] music +#define svc_finale 31 // [string] music [string] text + +#define svc_cdtrack 32 // [byte] track [byte] looptrack +#define svc_sellscreen 33 + +#define svc_cutscene 34 + +// +// client to server +// +#define clc_bad 0 +#define clc_nop 1 +#define clc_disconnect 2 +#define clc_move 3 // [usercmd_t] +#define clc_stringcmd 4 // [string] message + + +// +// temp entity events +// +#define TE_SPIKE 0 +#define TE_SUPERSPIKE 1 +#define TE_GUNSHOT 2 +#define TE_EXPLOSION 3 +#define TE_TAREXPLOSION 4 +#define TE_LIGHTNING1 5 +#define TE_LIGHTNING2 6 +#define TE_WIZSPIKE 7 +#define TE_KNIGHTSPIKE 8 +#define TE_LIGHTNING3 9 +#define TE_LAVASPLASH 10 +#define TE_TELEPORT 11 +#define TE_EXPLOSION2 12 + +// PGM 01/21/97 +#define TE_BEAM 13 +// PGM 01/21/97 + +#ifdef QUAKE2 +#define TE_IMPLOSION 14 +#define TE_RAILTRAIL 15 +#endif diff --git a/WinQuake/q.bat b/WinQuake/q.bat index 5726fcb..634a8f8 100644 --- a/WinQuake/q.bat +++ b/WinQuake/q.bat @@ -1 +1 @@ -dos\quake -basedir /quake -game test_gjc %1 %2 %3 %4 %5 %6 %7 %8 %9 +dos\quake -basedir /quake -game test_gjc %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/WinQuake/qa.bat b/WinQuake/qa.bat index f6db109..b844334 100644 --- a/WinQuake/qa.bat +++ b/WinQuake/qa.bat @@ -1 +1 @@ -dos\quake -nocdaudio -basedir /quake -game test_am %1 %2 %3 %4 %5 %6 %7 %8 %9 +dos\quake -nocdaudio -basedir /quake -game test_am %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/WinQuake/qb.bat b/WinQuake/qb.bat index 9eeb99d..84af0d7 100644 --- a/WinQuake/qb.bat +++ b/WinQuake/qb.bat @@ -1 +1 @@ -dos\quake /quake/test_gjc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9 +dos\quake /quake/test_gjc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/WinQuake/qt.bat b/WinQuake/qt.bat index d42b93c..1050178 100644 --- a/WinQuake/qt.bat +++ b/WinQuake/qt.bat @@ -1 +1 @@ -dos\quake /quake/test_am;/quake/test_jc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9 +dos\quake /quake/test_am;/quake/test_jc;/quake/id1 %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/WinQuake/quake-data.spec.sh b/WinQuake/quake-data.spec.sh old mode 100644 new mode 100755 diff --git a/WinQuake/quake-hipnotic.spec.sh b/WinQuake/quake-hipnotic.spec.sh old mode 100644 new mode 100755 diff --git a/WinQuake/quake-rogue.spec.sh b/WinQuake/quake-rogue.spec.sh old mode 100644 new mode 100755 diff --git a/WinQuake/quake-shareware.spec.sh b/WinQuake/quake-shareware.spec.sh old mode 100644 new mode 100755 diff --git a/WinQuake/quake.spec.sh b/WinQuake/quake.spec.sh old mode 100644 new mode 100755 diff --git a/WinQuake/quakeasm.h b/WinQuake/quakeasm.h index 96b758b..0c52eb2 100644 --- a/WinQuake/quakeasm.h +++ b/WinQuake/quakeasm.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // quakeasm.h: general asm header file // diff --git a/WinQuake/quakedef.h b/WinQuake/quakedef.h index e451827..d0aabaf 100644 --- a/WinQuake/quakedef.h +++ b/WinQuake/quakedef.h @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // quakedef.h -- primary header for client //#define GLTEST // experimental stuff diff --git a/WinQuake/r_aclip.c b/WinQuake/r_aclip.c index 61fef0c..2d8dbbd 100644 --- a/WinQuake/r_aclip.c +++ b/WinQuake/r_aclip.c @@ -1,350 +1,350 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_aclip.c: clip routines for drawing Alias models directly to the screen - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - -static finalvert_t fv[2][8]; -static auxvert_t av[8]; - -void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); -void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out); -void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out); -void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out); -void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out); - - -/* -================ -R_Alias_clip_z - -pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex -================ -*/ -void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - auxvert_t *pav0, *pav1, avout; - - pav0 = &av[pfv0 - &fv[0][0]]; - pav1 = &av[pfv1 - &fv[0][0]]; - - if (pfv0->v[1] >= pfv1->v[1]) - { - scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / - (pav1->fv[2] - pav0->fv[2]); - - avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; - avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; - avout.fv[2] = ALIAS_Z_CLIP_PLANE; - - out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale; - out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale; - out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale; - } - else - { - scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / - (pav0->fv[2] - pav1->fv[2]); - - avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; - avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; - avout.fv[2] = ALIAS_Z_CLIP_PLANE; - - out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale; - out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale; - out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale; - } - - R_AliasProjectFinalVert (out, &avout); - - if (out->v[0] < r_refdef.aliasvrect.x) - out->flags |= ALIAS_LEFT_CLIP; - if (out->v[1] < r_refdef.aliasvrect.y) - out->flags |= ALIAS_TOP_CLIP; - if (out->v[0] > r_refdef.aliasvrectright) - out->flags |= ALIAS_RIGHT_CLIP; - if (out->v[1] > r_refdef.aliasvrectbottom) - out->flags |= ALIAS_BOTTOM_CLIP; -} - - -#if !id386 - -void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) - { - scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) / - (pfv1->v[0] - pfv0->v[0]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; - } - else - { - scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) / - (pfv0->v[0] - pfv1->v[0]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; - } -} - - -void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) - { - scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) / - (pfv1->v[0] - pfv0->v[0]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; - } - else - { - scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) / - (pfv0->v[0] - pfv1->v[0]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; - } -} - - -void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) - { - scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) / - (pfv1->v[1] - pfv0->v[1]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; - } - else - { - scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) / - (pfv0->v[1] - pfv1->v[1]); - for (i=0 ; i<6 ; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; - } -} - - -void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) - { - scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) / - (pfv1->v[1] - pfv0->v[1]); - - for (i=0 ; i<6 ; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; - } - else - { - scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) / - (pfv0->v[1] - pfv1->v[1]); - - for (i=0 ; i<6 ; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; - } -} - -#endif - - -int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, - void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) ) -{ - int i,j,k; - int flags, oldflags; - - j = count-1; - k = 0; - for (i=0 ; i r_refdef.aliasvrectright) - out[k].flags |= ALIAS_RIGHT_CLIP; - if (out[k].v[1] > r_refdef.aliasvrectbottom) - out[k].flags |= ALIAS_BOTTOM_CLIP; - k++; - } - if (!flags) - { - out[k] = in[i]; - k++; - } - } - - return k; -} - - -/* -================ -R_AliasClipTriangle -================ -*/ -void R_AliasClipTriangle (mtriangle_t *ptri) -{ - int i, k, pingpong; - mtriangle_t mtri; - unsigned clipflags; - -// copy vertexes and fix seam texture coordinates - if (ptri->facesfront) - { - fv[0][0] = pfinalverts[ptri->vertindex[0]]; - fv[0][1] = pfinalverts[ptri->vertindex[1]]; - fv[0][2] = pfinalverts[ptri->vertindex[2]]; - } - else - { - for (i=0 ; i<3 ; i++) - { - fv[0][i] = pfinalverts[ptri->vertindex[i]]; - - if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) ) - fv[0][i].v[2] += r_affinetridesc.seamfixupX16; - } - } - -// clip - clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; - - if (clipflags & ALIAS_Z_CLIP) - { - for (i=0 ; i<3 ; i++) - av[i] = pauxverts[ptri->vertindex[i]]; - - k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); - if (k == 0) - return; - - pingpong = 1; - clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; - } - else - { - pingpong = 0; - k = 3; - } - - if (clipflags & ALIAS_LEFT_CLIP) - { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_LEFT_CLIP, k, R_Alias_clip_left); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_RIGHT_CLIP) - { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_RIGHT_CLIP, k, R_Alias_clip_right); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_BOTTOM_CLIP) - { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_TOP_CLIP) - { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_TOP_CLIP, k, R_Alias_clip_top); - if (k == 0) - return; - - pingpong ^= 1; - } - - for (i=0 ; i r_refdef.aliasvrectright) - fv[pingpong][i].v[0] = r_refdef.aliasvrectright; - - if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) - fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; - else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) - fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; - - fv[pingpong][i].flags = 0; - } - -// draw triangles - mtri.facesfront = ptri->facesfront; - r_affinetridesc.ptriangles = &mtri; - r_affinetridesc.pfinalverts = fv[pingpong]; - -// FIXME: do all at once as trifan? - mtri.vertindex[0] = 0; - for (i=1 ; iv[1] >= pfv1->v[1]) + { + scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / + (pav1->fv[2] - pav0->fv[2]); + + avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; + avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; + avout.fv[2] = ALIAS_Z_CLIP_PLANE; + + out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale; + out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale; + out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale; + } + else + { + scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / + (pav0->fv[2] - pav1->fv[2]); + + avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; + avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; + avout.fv[2] = ALIAS_Z_CLIP_PLANE; + + out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale; + out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale; + out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale; + } + + R_AliasProjectFinalVert (out, &avout); + + if (out->v[0] < r_refdef.aliasvrect.x) + out->flags |= ALIAS_LEFT_CLIP; + if (out->v[1] < r_refdef.aliasvrect.y) + out->flags |= ALIAS_TOP_CLIP; + if (out->v[0] > r_refdef.aliasvrectright) + out->flags |= ALIAS_RIGHT_CLIP; + if (out->v[1] > r_refdef.aliasvrectbottom) + out->flags |= ALIAS_BOTTOM_CLIP; +} + + +#if !id386 + +void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) + { + scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) / + (pfv1->v[0] - pfv0->v[0]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; + } + else + { + scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) / + (pfv0->v[0] - pfv1->v[0]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; + } +} + + +void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) + { + scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) / + (pfv1->v[0] - pfv0->v[0]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; + } + else + { + scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) / + (pfv0->v[0] - pfv1->v[0]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; + } +} + + +void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) + { + scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) / + (pfv1->v[1] - pfv0->v[1]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; + } + else + { + scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) / + (pfv0->v[1] - pfv1->v[1]); + for (i=0 ; i<6 ; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; + } +} + + +void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) + { + scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) / + (pfv1->v[1] - pfv0->v[1]); + + for (i=0 ; i<6 ; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5; + } + else + { + scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) / + (pfv0->v[1] - pfv1->v[1]); + + for (i=0 ; i<6 ; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5; + } +} + +#endif + + +int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, + void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) ) +{ + int i,j,k; + int flags, oldflags; + + j = count-1; + k = 0; + for (i=0 ; i r_refdef.aliasvrectright) + out[k].flags |= ALIAS_RIGHT_CLIP; + if (out[k].v[1] > r_refdef.aliasvrectbottom) + out[k].flags |= ALIAS_BOTTOM_CLIP; + k++; + } + if (!flags) + { + out[k] = in[i]; + k++; + } + } + + return k; +} + + +/* +================ +R_AliasClipTriangle +================ +*/ +void R_AliasClipTriangle (mtriangle_t *ptri) +{ + int i, k, pingpong; + mtriangle_t mtri; + unsigned clipflags; + +// copy vertexes and fix seam texture coordinates + if (ptri->facesfront) + { + fv[0][0] = pfinalverts[ptri->vertindex[0]]; + fv[0][1] = pfinalverts[ptri->vertindex[1]]; + fv[0][2] = pfinalverts[ptri->vertindex[2]]; + } + else + { + for (i=0 ; i<3 ; i++) + { + fv[0][i] = pfinalverts[ptri->vertindex[i]]; + + if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) ) + fv[0][i].v[2] += r_affinetridesc.seamfixupX16; + } + } + +// clip + clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; + + if (clipflags & ALIAS_Z_CLIP) + { + for (i=0 ; i<3 ; i++) + av[i] = pauxverts[ptri->vertindex[i]]; + + k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); + if (k == 0) + return; + + pingpong = 1; + clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; + } + else + { + pingpong = 0; + k = 3; + } + + if (clipflags & ALIAS_LEFT_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_LEFT_CLIP, k, R_Alias_clip_left); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_RIGHT_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_RIGHT_CLIP, k, R_Alias_clip_right); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_BOTTOM_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_TOP_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_TOP_CLIP, k, R_Alias_clip_top); + if (k == 0) + return; + + pingpong ^= 1; + } + + for (i=0 ; i r_refdef.aliasvrectright) + fv[pingpong][i].v[0] = r_refdef.aliasvrectright; + + if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) + fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; + else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) + fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; + + fv[pingpong][i].flags = 0; + } + +// draw triangles + mtri.facesfront = ptri->facesfront; + r_affinetridesc.ptriangles = &mtri; + r_affinetridesc.pfinalverts = fv[pingpong]; + +// FIXME: do all at once as trifan? + mtri.vertindex[0] = 0; + for (i=1 ; itrivial_accept = 0; - pmodel = currententity->model; - pahdr = Mod_Extradata (pmodel); - pmdl = (mdl_t *)((byte *)pahdr + pahdr->model); - - R_AliasSetUpTransform (0); - -// construct the base bounding box for this frame - frame = currententity->frame; -// TODO: don't repeat this check when drawing? - if ((frame >= pmdl->numframes) || (frame < 0)) - { - Con_DPrintf ("No such frame %d %s\n", frame, - pmodel->name); - frame = 0; - } - - pframedesc = &pahdr->frames[frame]; - -// x worldspace coordinates - basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = - (float)pframedesc->bboxmin.v[0]; - basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = - (float)pframedesc->bboxmax.v[0]; - -// y worldspace coordinates - basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = - (float)pframedesc->bboxmin.v[1]; - basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = - (float)pframedesc->bboxmax.v[1]; - -// z worldspace coordinates - basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = - (float)pframedesc->bboxmin.v[2]; - basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = - (float)pframedesc->bboxmax.v[2]; - - zclipped = false; - zfullyclipped = true; - - minz = 9999; - for (i=0; i<8 ; i++) - { - R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); - - if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) - { - // we must clip points that are closer than the near clip plane - viewpts[i].flags = ALIAS_Z_CLIP; - zclipped = true; - } - else - { - if (viewaux[i].fv[2] < minz) - minz = viewaux[i].fv[2]; - viewpts[i].flags = 0; - zfullyclipped = false; - } - } - - - if (zfullyclipped) - { - return false; // everything was near-z-clipped - } - - numv = 8; - - if (zclipped) - { - // organize points by edges, use edges to get new points (possible trivial - // reject) - for (i=0 ; i<12 ; i++) - { - // edge endpoints - pv0 = &viewpts[aedges[i].index0]; - pv1 = &viewpts[aedges[i].index1]; - pa0 = &viewaux[aedges[i].index0]; - pa1 = &viewaux[aedges[i].index1]; - - // if one end is clipped and the other isn't, make a new point - if (pv0->flags ^ pv1->flags) - { - frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / - (pa1->fv[2] - pa0->fv[2]); - viewaux[numv].fv[0] = pa0->fv[0] + - (pa1->fv[0] - pa0->fv[0]) * frac; - viewaux[numv].fv[1] = pa0->fv[1] + - (pa1->fv[1] - pa0->fv[1]) * frac; - viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; - viewpts[numv].flags = 0; - numv++; - } - } - } - -// project the vertices that remain after clipping - anyclip = 0; - allclip = ALIAS_XY_CLIP_MASK; - -// TODO: probably should do this loop in ASM, especially if we use floats - for (i=0 ; i r_refdef.fvrectright) - flags |= ALIAS_RIGHT_CLIP; - if (v1 > r_refdef.fvrectbottom) - flags |= ALIAS_BOTTOM_CLIP; - - anyclip |= flags; - allclip &= flags; - } - - if (allclip) - return false; // trivial reject off one side - - currententity->trivial_accept = !anyclip & !zclipped; - - if (currententity->trivial_accept) - { - if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) - { - currententity->trivial_accept |= 2; - } - } - - return true; -} - - -/* -================ -R_AliasTransformVector -================ -*/ -void R_AliasTransformVector (vec3_t in, vec3_t out) -{ - out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; - out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; - out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3]; -} - - -/* -================ -R_AliasPreparePoints - -General clipped case -================ -*/ -void R_AliasPreparePoints (void) -{ - int i; - stvert_t *pstverts; - finalvert_t *fv; - auxvert_t *av; - mtriangle_t *ptri; - finalvert_t *pfv[3]; - - pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); - r_anumverts = pmdl->numverts; - fv = pfinalverts; - av = pauxverts; - - for (i=0 ; ifv[2] < ALIAS_Z_CLIP_PLANE) - fv->flags |= ALIAS_Z_CLIP; - else - { - R_AliasProjectFinalVert (fv, av); - - if (fv->v[0] < r_refdef.aliasvrect.x) - fv->flags |= ALIAS_LEFT_CLIP; - if (fv->v[1] < r_refdef.aliasvrect.y) - fv->flags |= ALIAS_TOP_CLIP; - if (fv->v[0] > r_refdef.aliasvrectright) - fv->flags |= ALIAS_RIGHT_CLIP; - if (fv->v[1] > r_refdef.aliasvrectbottom) - fv->flags |= ALIAS_BOTTOM_CLIP; - } - } - -// -// clip and draw all triangles -// - r_affinetridesc.numtriangles = 1; - - ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles); - for (i=0 ; inumtris ; i++, ptri++) - { - pfv[0] = &pfinalverts[ptri->vertindex[0]]; - pfv[1] = &pfinalverts[ptri->vertindex[1]]; - pfv[2] = &pfinalverts[ptri->vertindex[2]]; - - if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) - continue; // completely clipped - - if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & - (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) ) - { // totally unclipped - r_affinetridesc.pfinalverts = pfinalverts; - r_affinetridesc.ptriangles = ptri; - D_PolysetDraw (); - } - else - { // partially clipped - R_AliasClipTriangle (ptri); - } - } -} - - -/* -================ -R_AliasSetUpTransform -================ -*/ -void R_AliasSetUpTransform (int trivial_accept) -{ - int i; - float rotationmatrix[3][4], t2matrix[3][4]; - static float tmatrix[3][4]; - static float viewmatrix[3][4]; - vec3_t angles; - -// TODO: should really be stored with the entity instead of being reconstructed -// TODO: should use a look-up table -// TODO: could cache lazily, stored in the entity - - angles[ROLL] = currententity->angles[ROLL]; - angles[PITCH] = -currententity->angles[PITCH]; - angles[YAW] = currententity->angles[YAW]; - AngleVectors (angles, alias_forward, alias_right, alias_up); - - tmatrix[0][0] = pmdl->scale[0]; - tmatrix[1][1] = pmdl->scale[1]; - tmatrix[2][2] = pmdl->scale[2]; - - tmatrix[0][3] = pmdl->scale_origin[0]; - tmatrix[1][3] = pmdl->scale_origin[1]; - tmatrix[2][3] = pmdl->scale_origin[2]; - -// TODO: can do this with simple matrix rearrangement - - for (i=0 ; i<3 ; i++) - { - t2matrix[i][0] = alias_forward[i]; - t2matrix[i][1] = -alias_right[i]; - t2matrix[i][2] = alias_up[i]; - } - - t2matrix[0][3] = -modelorg[0]; - t2matrix[1][3] = -modelorg[1]; - t2matrix[2][3] = -modelorg[2]; - -// FIXME: can do more efficiently than full concatenation - R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); - -// TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); - VectorInverse (viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); - -// viewmatrix[0][3] = 0; -// viewmatrix[1][3] = 0; -// viewmatrix[2][3] = 0; - - R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); - -// do the scaling up of x and y to screen coordinates as part of the transform -// for the unclipped case (it would mess up clipping in the clipped case). -// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y -// correspondingly so the projected x and y come out right -// FIXME: make this work for clipped case too? - if (trivial_accept) - { - for (i=0 ; i<4 ; i++) - { - aliastransform[0][i] *= aliasxscale * - (1.0 / ((float)0x8000 * 0x10000)); - aliastransform[1][i] *= aliasyscale * - (1.0 / ((float)0x8000 * 0x10000)); - aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); - - } - } -} - - -/* -================ -R_AliasTransformFinalVert -================ -*/ -void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, - trivertx_t *pverts, stvert_t *pstverts) -{ - int temp; - float lightcos, *plightnormal; - - av->fv[0] = DotProduct(pverts->v, aliastransform[0]) + - aliastransform[0][3]; - av->fv[1] = DotProduct(pverts->v, aliastransform[1]) + - aliastransform[1][3]; - av->fv[2] = DotProduct(pverts->v, aliastransform[2]) + - aliastransform[2][3]; - - fv->v[2] = pstverts->s; - fv->v[3] = pstverts->t; - - fv->flags = pstverts->onseam; - -// lighting - plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = DotProduct (plightnormal, r_plightvec); - temp = r_ambientlight; - - if (lightcos < 0) - { - temp += (int)(r_shadelight * lightcos); - - // clamp; because we limited the minimum ambient and shading light, we - // don't have to clamp low light, just bright - if (temp < 0) - temp = 0; - } - - fv->v[4] = temp; -} - - -#if !id386 - -/* -================ -R_AliasTransformAndProjectFinalVerts -================ -*/ -void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) -{ - int i, temp; - float lightcos, *plightnormal, zi; - trivertx_t *pverts; - - pverts = r_apverts; - - for (i=0 ; iv, aliastransform[2]) + - aliastransform[2][3]); - - // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is - // scaled up by 1/2**31, and the scaling cancels out for x and y in the - // projection - fv->v[5] = zi; - - fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + - aliastransform[0][3]) * zi) + aliasxcenter; - fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + - aliastransform[1][3]) * zi) + aliasycenter; - - fv->v[2] = pstverts->s; - fv->v[3] = pstverts->t; - fv->flags = pstverts->onseam; - - // lighting - plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = DotProduct (plightnormal, r_plightvec); - temp = r_ambientlight; - - if (lightcos < 0) - { - temp += (int)(r_shadelight * lightcos); - - // clamp; because we limited the minimum ambient and shading light, we - // don't have to clamp low light, just bright - if (temp < 0) - temp = 0; - } - - fv->v[4] = temp; - } -} - -#endif - - -/* -================ -R_AliasProjectFinalVert -================ -*/ -void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) -{ - float zi; - -// project points - zi = 1.0 / av->fv[2]; - - fv->v[5] = zi * ziscale; - - fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; - fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter; -} - - -/* -================ -R_AliasPrepareUnclippedPoints -================ -*/ -void R_AliasPrepareUnclippedPoints (void) -{ - stvert_t *pstverts; - finalvert_t *fv; - - pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); - r_anumverts = pmdl->numverts; -// FIXME: just use pfinalverts directly? - fv = pfinalverts; - - R_AliasTransformAndProjectFinalVerts (fv, pstverts); - - if (r_affinetridesc.drawtype) - D_PolysetDrawFinalVerts (fv, r_anumverts); - - r_affinetridesc.pfinalverts = pfinalverts; - r_affinetridesc.ptriangles = (mtriangle_t *) - ((byte *)paliashdr + paliashdr->triangles); - r_affinetridesc.numtriangles = pmdl->numtris; - - D_PolysetDraw (); -} - -/* -=============== -R_AliasSetupSkin -=============== -*/ -void R_AliasSetupSkin (void) -{ - int skinnum; - int i, numskins; - maliasskingroup_t *paliasskingroup; - float *pskinintervals, fullskininterval; - float skintargettime, skintime; - - skinnum = currententity->skinnum; - if ((skinnum >= pmdl->numskins) || (skinnum < 0)) - { - Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum); - skinnum = 0; - } - - pskindesc = ((maliasskindesc_t *) - ((byte *)paliashdr + paliashdr->skindesc)) + skinnum; - a_skinwidth = pmdl->skinwidth; - - if (pskindesc->type == ALIAS_SKIN_GROUP) - { - paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr + - pskindesc->skin); - pskinintervals = (float *) - ((byte *)paliashdr + paliasskingroup->intervals); - numskins = paliasskingroup->numskins; - fullskininterval = pskinintervals[numskins-1]; - - skintime = cl.time + currententity->syncbase; - - // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval - // values are positive, so we don't have to worry about division by 0 - skintargettime = skintime - - ((int)(skintime / fullskininterval)) * fullskininterval; - - for (i=0 ; i<(numskins-1) ; i++) - { - if (pskinintervals[i] > skintargettime) - break; - } - - pskindesc = &paliasskingroup->skindescs[i]; - } - - r_affinetridesc.pskindesc = pskindesc; - r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin); - r_affinetridesc.skinwidth = a_skinwidth; - r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; - r_affinetridesc.skinheight = pmdl->skinheight; -} - -/* -================ -R_AliasSetupLighting -================ -*/ -void R_AliasSetupLighting (alight_t *plighting) -{ - -// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have -// to clamp off the bottom - r_ambientlight = plighting->ambientlight; - - if (r_ambientlight < LIGHT_MIN) - r_ambientlight = LIGHT_MIN; - - r_ambientlight = (255 - r_ambientlight) << VID_CBITS; - - if (r_ambientlight < LIGHT_MIN) - r_ambientlight = LIGHT_MIN; - - r_shadelight = plighting->shadelight; - - if (r_shadelight < 0) - r_shadelight = 0; - - r_shadelight *= VID_GRADES; - -// rotate the lighting vector into the model's frame of reference - r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); - r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); - r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); -} - -/* -================= -R_AliasSetupFrame - -set r_apverts -================= -*/ -void R_AliasSetupFrame (void) -{ - int frame; - int i, numframes; - maliasgroup_t *paliasgroup; - float *pintervals, fullinterval, targettime, time; - - frame = currententity->frame; - if ((frame >= pmdl->numframes) || (frame < 0)) - { - Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - if (paliashdr->frames[frame].type == ALIAS_SINGLE) - { - r_apverts = (trivertx_t *) - ((byte *)paliashdr + paliashdr->frames[frame].frame); - return; - } - - paliasgroup = (maliasgroup_t *) - ((byte *)paliashdr + paliashdr->frames[frame].frame); - pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals); - numframes = paliasgroup->numframes; - fullinterval = pintervals[numframes-1]; - - time = cl.time + currententity->syncbase; - -// -// when loading in Mod_LoadAliasGroup, we guaranteed all interval values -// are positive, so we don't have to worry about division by 0 -// - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - } - - r_apverts = (trivertx_t *) - ((byte *)paliashdr + paliasgroup->frames[i].frame); -} - - -/* -================ -R_AliasDrawModel -================ -*/ -void R_AliasDrawModel (alight_t *plighting) -{ - finalvert_t finalverts[MAXALIASVERTS + - ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; - auxvert_t auxverts[MAXALIASVERTS]; - - r_amodels_drawn++; - -// cache align - pfinalverts = (finalvert_t *) - (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - pauxverts = &auxverts[0]; - - paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); - pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); - - R_AliasSetupSkin (); - R_AliasSetUpTransform (currententity->trivial_accept); - R_AliasSetupLighting (plighting); - R_AliasSetupFrame (); - - if (!currententity->colormap) - Sys_Error ("R_AliasDrawModel: !currententity->colormap"); - - r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && - r_recursiveaffinetriangles; - - if (r_affinetridesc.drawtype) - { - D_PolysetUpdateTables (); // FIXME: precalc... - } - else - { -#if id386 - D_Aff8Patch (currententity->colormap); -#endif - } - - acolormap = currententity->colormap; - - if (currententity != &cl.viewent) - ziscale = (float)0x8000 * (float)0x10000; - else - ziscale = (float)0x8000 * (float)0x10000 * 3.0; - - if (currententity->trivial_accept) - R_AliasPrepareUnclippedPoints (); - else - R_AliasPreparePoints (); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_alias.c: routines for setting up to draw alias models + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" // FIXME: shouldn't be needed (is needed for patch + // right now, but that should move) + +#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the + // need for inner-loop light clamping + +mtriangle_t *ptriangles; +affinetridesc_t r_affinetridesc; + +void * acolormap; // FIXME: should go away + +trivertx_t *r_apverts; + +// TODO: these probably will go away with optimized rasterization +mdl_t *pmdl; +vec3_t r_plightvec; +int r_ambientlight; +float r_shadelight; +aliashdr_t *paliashdr; +finalvert_t *pfinalverts; +auxvert_t *pauxverts; +static float ziscale; +static model_t *pmodel; + +static vec3_t alias_forward, alias_right, alias_up; + +static maliasskindesc_t *pskindesc; + +int r_amodels_drawn; +int a_skinwidth; +int r_anumverts; + +float aliastransform[3][4]; + +typedef struct { + int index0; + int index1; +} aedge_t; + +static aedge_t aedges[12] = { +{0, 1}, {1, 2}, {2, 3}, {3, 0}, +{4, 5}, {5, 6}, {6, 7}, {7, 4}, +{0, 5}, {1, 4}, {2, 7}, {3, 6} +}; + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + +void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, + stvert_t *pstverts); +void R_AliasSetUpTransform (int trivial_accept); +void R_AliasTransformVector (vec3_t in, vec3_t out); +void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, + trivertx_t *pverts, stvert_t *pstverts); +void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); + + +/* +================ +R_AliasCheckBBox +================ +*/ +qboolean R_AliasCheckBBox (void) +{ + int i, flags, frame, numv; + aliashdr_t *pahdr; + float zi, basepts[8][3], v0, v1, frac; + finalvert_t *pv0, *pv1, viewpts[16]; + auxvert_t *pa0, *pa1, viewaux[16]; + maliasframedesc_t *pframedesc; + qboolean zclipped, zfullyclipped; + unsigned anyclip, allclip; + int minz; + +// expand, rotate, and translate points into worldspace + + currententity->trivial_accept = 0; + pmodel = currententity->model; + pahdr = Mod_Extradata (pmodel); + pmdl = (mdl_t *)((byte *)pahdr + pahdr->model); + + R_AliasSetUpTransform (0); + +// construct the base bounding box for this frame + frame = currententity->frame; +// TODO: don't repeat this check when drawing? + if ((frame >= pmdl->numframes) || (frame < 0)) + { + Con_DPrintf ("No such frame %d %s\n", frame, + pmodel->name); + frame = 0; + } + + pframedesc = &pahdr->frames[frame]; + +// x worldspace coordinates + basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = + (float)pframedesc->bboxmin.v[0]; + basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = + (float)pframedesc->bboxmax.v[0]; + +// y worldspace coordinates + basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = + (float)pframedesc->bboxmin.v[1]; + basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = + (float)pframedesc->bboxmax.v[1]; + +// z worldspace coordinates + basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = + (float)pframedesc->bboxmin.v[2]; + basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = + (float)pframedesc->bboxmax.v[2]; + + zclipped = false; + zfullyclipped = true; + + minz = 9999; + for (i=0; i<8 ; i++) + { + R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); + + if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) + { + // we must clip points that are closer than the near clip plane + viewpts[i].flags = ALIAS_Z_CLIP; + zclipped = true; + } + else + { + if (viewaux[i].fv[2] < minz) + minz = viewaux[i].fv[2]; + viewpts[i].flags = 0; + zfullyclipped = false; + } + } + + + if (zfullyclipped) + { + return false; // everything was near-z-clipped + } + + numv = 8; + + if (zclipped) + { + // organize points by edges, use edges to get new points (possible trivial + // reject) + for (i=0 ; i<12 ; i++) + { + // edge endpoints + pv0 = &viewpts[aedges[i].index0]; + pv1 = &viewpts[aedges[i].index1]; + pa0 = &viewaux[aedges[i].index0]; + pa1 = &viewaux[aedges[i].index1]; + + // if one end is clipped and the other isn't, make a new point + if (pv0->flags ^ pv1->flags) + { + frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / + (pa1->fv[2] - pa0->fv[2]); + viewaux[numv].fv[0] = pa0->fv[0] + + (pa1->fv[0] - pa0->fv[0]) * frac; + viewaux[numv].fv[1] = pa0->fv[1] + + (pa1->fv[1] - pa0->fv[1]) * frac; + viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; + viewpts[numv].flags = 0; + numv++; + } + } + } + +// project the vertices that remain after clipping + anyclip = 0; + allclip = ALIAS_XY_CLIP_MASK; + +// TODO: probably should do this loop in ASM, especially if we use floats + for (i=0 ; i r_refdef.fvrectright) + flags |= ALIAS_RIGHT_CLIP; + if (v1 > r_refdef.fvrectbottom) + flags |= ALIAS_BOTTOM_CLIP; + + anyclip |= flags; + allclip &= flags; + } + + if (allclip) + return false; // trivial reject off one side + + currententity->trivial_accept = !anyclip & !zclipped; + + if (currententity->trivial_accept) + { + if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) + { + currententity->trivial_accept |= 2; + } + } + + return true; +} + + +/* +================ +R_AliasTransformVector +================ +*/ +void R_AliasTransformVector (vec3_t in, vec3_t out) +{ + out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; + out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; + out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3]; +} + + +/* +================ +R_AliasPreparePoints + +General clipped case +================ +*/ +void R_AliasPreparePoints (void) +{ + int i; + stvert_t *pstverts; + finalvert_t *fv; + auxvert_t *av; + mtriangle_t *ptri; + finalvert_t *pfv[3]; + + pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); + r_anumverts = pmdl->numverts; + fv = pfinalverts; + av = pauxverts; + + for (i=0 ; ifv[2] < ALIAS_Z_CLIP_PLANE) + fv->flags |= ALIAS_Z_CLIP; + else + { + R_AliasProjectFinalVert (fv, av); + + if (fv->v[0] < r_refdef.aliasvrect.x) + fv->flags |= ALIAS_LEFT_CLIP; + if (fv->v[1] < r_refdef.aliasvrect.y) + fv->flags |= ALIAS_TOP_CLIP; + if (fv->v[0] > r_refdef.aliasvrectright) + fv->flags |= ALIAS_RIGHT_CLIP; + if (fv->v[1] > r_refdef.aliasvrectbottom) + fv->flags |= ALIAS_BOTTOM_CLIP; + } + } + +// +// clip and draw all triangles +// + r_affinetridesc.numtriangles = 1; + + ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles); + for (i=0 ; inumtris ; i++, ptri++) + { + pfv[0] = &pfinalverts[ptri->vertindex[0]]; + pfv[1] = &pfinalverts[ptri->vertindex[1]]; + pfv[2] = &pfinalverts[ptri->vertindex[2]]; + + if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) + continue; // completely clipped + + if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & + (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) ) + { // totally unclipped + r_affinetridesc.pfinalverts = pfinalverts; + r_affinetridesc.ptriangles = ptri; + D_PolysetDraw (); + } + else + { // partially clipped + R_AliasClipTriangle (ptri); + } + } +} + + +/* +================ +R_AliasSetUpTransform +================ +*/ +void R_AliasSetUpTransform (int trivial_accept) +{ + int i; + float rotationmatrix[3][4], t2matrix[3][4]; + static float tmatrix[3][4]; + static float viewmatrix[3][4]; + vec3_t angles; + +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: should use a look-up table +// TODO: could cache lazily, stored in the entity + + angles[ROLL] = currententity->angles[ROLL]; + angles[PITCH] = -currententity->angles[PITCH]; + angles[YAW] = currententity->angles[YAW]; + AngleVectors (angles, alias_forward, alias_right, alias_up); + + tmatrix[0][0] = pmdl->scale[0]; + tmatrix[1][1] = pmdl->scale[1]; + tmatrix[2][2] = pmdl->scale[2]; + + tmatrix[0][3] = pmdl->scale_origin[0]; + tmatrix[1][3] = pmdl->scale_origin[1]; + tmatrix[2][3] = pmdl->scale_origin[2]; + +// TODO: can do this with simple matrix rearrangement + + for (i=0 ; i<3 ; i++) + { + t2matrix[i][0] = alias_forward[i]; + t2matrix[i][1] = -alias_right[i]; + t2matrix[i][2] = alias_up[i]; + } + + t2matrix[0][3] = -modelorg[0]; + t2matrix[1][3] = -modelorg[1]; + t2matrix[2][3] = -modelorg[2]; + +// FIXME: can do more efficiently than full concatenation + R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); + +// TODO: should be global, set when vright, etc., set + VectorCopy (vright, viewmatrix[0]); + VectorCopy (vup, viewmatrix[1]); + VectorInverse (viewmatrix[1]); + VectorCopy (vpn, viewmatrix[2]); + +// viewmatrix[0][3] = 0; +// viewmatrix[1][3] = 0; +// viewmatrix[2][3] = 0; + + R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); + +// do the scaling up of x and y to screen coordinates as part of the transform +// for the unclipped case (it would mess up clipping in the clipped case). +// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y +// correspondingly so the projected x and y come out right +// FIXME: make this work for clipped case too? + if (trivial_accept) + { + for (i=0 ; i<4 ; i++) + { + aliastransform[0][i] *= aliasxscale * + (1.0 / ((float)0x8000 * 0x10000)); + aliastransform[1][i] *= aliasyscale * + (1.0 / ((float)0x8000 * 0x10000)); + aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); + + } + } +} + + +/* +================ +R_AliasTransformFinalVert +================ +*/ +void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, + trivertx_t *pverts, stvert_t *pstverts) +{ + int temp; + float lightcos, *plightnormal; + + av->fv[0] = DotProduct(pverts->v, aliastransform[0]) + + aliastransform[0][3]; + av->fv[1] = DotProduct(pverts->v, aliastransform[1]) + + aliastransform[1][3]; + av->fv[2] = DotProduct(pverts->v, aliastransform[2]) + + aliastransform[2][3]; + + fv->v[2] = pstverts->s; + fv->v[3] = pstverts->t; + + fv->flags = pstverts->onseam; + +// lighting + plightnormal = r_avertexnormals[pverts->lightnormalindex]; + lightcos = DotProduct (plightnormal, r_plightvec); + temp = r_ambientlight; + + if (lightcos < 0) + { + temp += (int)(r_shadelight * lightcos); + + // clamp; because we limited the minimum ambient and shading light, we + // don't have to clamp low light, just bright + if (temp < 0) + temp = 0; + } + + fv->v[4] = temp; +} + + +#if !id386 + +/* +================ +R_AliasTransformAndProjectFinalVerts +================ +*/ +void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) +{ + int i, temp; + float lightcos, *plightnormal, zi; + trivertx_t *pverts; + + pverts = r_apverts; + + for (i=0 ; iv, aliastransform[2]) + + aliastransform[2][3]); + + // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is + // scaled up by 1/2**31, and the scaling cancels out for x and y in the + // projection + fv->v[5] = zi; + + fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + + aliastransform[0][3]) * zi) + aliasxcenter; + fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + + aliastransform[1][3]) * zi) + aliasycenter; + + fv->v[2] = pstverts->s; + fv->v[3] = pstverts->t; + fv->flags = pstverts->onseam; + + // lighting + plightnormal = r_avertexnormals[pverts->lightnormalindex]; + lightcos = DotProduct (plightnormal, r_plightvec); + temp = r_ambientlight; + + if (lightcos < 0) + { + temp += (int)(r_shadelight * lightcos); + + // clamp; because we limited the minimum ambient and shading light, we + // don't have to clamp low light, just bright + if (temp < 0) + temp = 0; + } + + fv->v[4] = temp; + } +} + +#endif + + +/* +================ +R_AliasProjectFinalVert +================ +*/ +void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) +{ + float zi; + +// project points + zi = 1.0 / av->fv[2]; + + fv->v[5] = zi * ziscale; + + fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; + fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter; +} + + +/* +================ +R_AliasPrepareUnclippedPoints +================ +*/ +void R_AliasPrepareUnclippedPoints (void) +{ + stvert_t *pstverts; + finalvert_t *fv; + + pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); + r_anumverts = pmdl->numverts; +// FIXME: just use pfinalverts directly? + fv = pfinalverts; + + R_AliasTransformAndProjectFinalVerts (fv, pstverts); + + if (r_affinetridesc.drawtype) + D_PolysetDrawFinalVerts (fv, r_anumverts); + + r_affinetridesc.pfinalverts = pfinalverts; + r_affinetridesc.ptriangles = (mtriangle_t *) + ((byte *)paliashdr + paliashdr->triangles); + r_affinetridesc.numtriangles = pmdl->numtris; + + D_PolysetDraw (); +} + +/* +=============== +R_AliasSetupSkin +=============== +*/ +void R_AliasSetupSkin (void) +{ + int skinnum; + int i, numskins; + maliasskingroup_t *paliasskingroup; + float *pskinintervals, fullskininterval; + float skintargettime, skintime; + + skinnum = currententity->skinnum; + if ((skinnum >= pmdl->numskins) || (skinnum < 0)) + { + Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum); + skinnum = 0; + } + + pskindesc = ((maliasskindesc_t *) + ((byte *)paliashdr + paliashdr->skindesc)) + skinnum; + a_skinwidth = pmdl->skinwidth; + + if (pskindesc->type == ALIAS_SKIN_GROUP) + { + paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr + + pskindesc->skin); + pskinintervals = (float *) + ((byte *)paliashdr + paliasskingroup->intervals); + numskins = paliasskingroup->numskins; + fullskininterval = pskinintervals[numskins-1]; + + skintime = cl.time + currententity->syncbase; + + // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval + // values are positive, so we don't have to worry about division by 0 + skintargettime = skintime - + ((int)(skintime / fullskininterval)) * fullskininterval; + + for (i=0 ; i<(numskins-1) ; i++) + { + if (pskinintervals[i] > skintargettime) + break; + } + + pskindesc = &paliasskingroup->skindescs[i]; + } + + r_affinetridesc.pskindesc = pskindesc; + r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin); + r_affinetridesc.skinwidth = a_skinwidth; + r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; + r_affinetridesc.skinheight = pmdl->skinheight; +} + +/* +================ +R_AliasSetupLighting +================ +*/ +void R_AliasSetupLighting (alight_t *plighting) +{ + +// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have +// to clamp off the bottom + r_ambientlight = plighting->ambientlight; + + if (r_ambientlight < LIGHT_MIN) + r_ambientlight = LIGHT_MIN; + + r_ambientlight = (255 - r_ambientlight) << VID_CBITS; + + if (r_ambientlight < LIGHT_MIN) + r_ambientlight = LIGHT_MIN; + + r_shadelight = plighting->shadelight; + + if (r_shadelight < 0) + r_shadelight = 0; + + r_shadelight *= VID_GRADES; + +// rotate the lighting vector into the model's frame of reference + r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); + r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); + r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); +} + +/* +================= +R_AliasSetupFrame + +set r_apverts +================= +*/ +void R_AliasSetupFrame (void) +{ + int frame; + int i, numframes; + maliasgroup_t *paliasgroup; + float *pintervals, fullinterval, targettime, time; + + frame = currententity->frame; + if ((frame >= pmdl->numframes) || (frame < 0)) + { + Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); + frame = 0; + } + + if (paliashdr->frames[frame].type == ALIAS_SINGLE) + { + r_apverts = (trivertx_t *) + ((byte *)paliashdr + paliashdr->frames[frame].frame); + return; + } + + paliasgroup = (maliasgroup_t *) + ((byte *)paliashdr + paliashdr->frames[frame].frame); + pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals); + numframes = paliasgroup->numframes; + fullinterval = pintervals[numframes-1]; + + time = cl.time + currententity->syncbase; + +// +// when loading in Mod_LoadAliasGroup, we guaranteed all interval values +// are positive, so we don't have to worry about division by 0 +// + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + for (i=0 ; i<(numframes-1) ; i++) + { + if (pintervals[i] > targettime) + break; + } + + r_apverts = (trivertx_t *) + ((byte *)paliashdr + paliasgroup->frames[i].frame); +} + + +/* +================ +R_AliasDrawModel +================ +*/ +void R_AliasDrawModel (alight_t *plighting) +{ + finalvert_t finalverts[MAXALIASVERTS + + ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; + auxvert_t auxverts[MAXALIASVERTS]; + + r_amodels_drawn++; + +// cache align + pfinalverts = (finalvert_t *) + (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + pauxverts = &auxverts[0]; + + paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); + pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); + + R_AliasSetupSkin (); + R_AliasSetUpTransform (currententity->trivial_accept); + R_AliasSetupLighting (plighting); + R_AliasSetupFrame (); + + if (!currententity->colormap) + Sys_Error ("R_AliasDrawModel: !currententity->colormap"); + + r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && + r_recursiveaffinetriangles; + + if (r_affinetridesc.drawtype) + { + D_PolysetUpdateTables (); // FIXME: precalc... + } + else + { +#if id386 + D_Aff8Patch (currententity->colormap); +#endif + } + + acolormap = currententity->colormap; + + if (currententity != &cl.viewent) + ziscale = (float)0x8000 * (float)0x10000; + else + ziscale = (float)0x8000 * (float)0x10000 * 3.0; + + if (currententity->trivial_accept) + R_AliasPrepareUnclippedPoints (); + else + R_AliasPreparePoints (); +} + diff --git a/WinQuake/r_aliasa.s b/WinQuake/r_aliasa.s index b19e97a..123cde2 100644 --- a/WinQuake/r_aliasa.s +++ b/WinQuake/r_aliasa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // r_aliasa.s // x86 assembly-language Alias model transform and project code. diff --git a/WinQuake/r_bsp.c b/WinQuake/r_bsp.c index 70e42f9..8114242 100644 --- a/WinQuake/r_bsp.c +++ b/WinQuake/r_bsp.c @@ -1,674 +1,674 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_bsp.c - -#include "quakedef.h" -#include "r_local.h" - -// -// current entity info -// -qboolean insubmodel; -entity_t *currententity; -vec3_t modelorg, base_modelorg; - // modelorg is the viewpoint reletive to - // the currently rendering entity -vec3_t r_entorigin; // the currently rendering entity in world - // coordinates - -float entity_rotation[3][3]; - -vec3_t r_worldmodelorg; - -int r_currentbkey; - -typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; - -#define MAX_BMODEL_VERTS 500 // 6K -#define MAX_BMODEL_EDGES 1000 // 12K - -static mvertex_t *pbverts; -static bedge_t *pbedges; -static int numbverts, numbedges; - -static mvertex_t *pfrontenter, *pfrontexit; - -static qboolean makeclippededge; - - -//=========================================================================== - -/* -================ -R_EntityRotate -================ -*/ -void R_EntityRotate (vec3_t vec) -{ - vec3_t tvec; - - VectorCopy (vec, tvec); - vec[0] = DotProduct (entity_rotation[0], tvec); - vec[1] = DotProduct (entity_rotation[1], tvec); - vec[2] = DotProduct (entity_rotation[2], tvec); -} - - -/* -================ -R_RotateBmodel -================ -*/ -void R_RotateBmodel (void) -{ - float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3]; - -// TODO: should use a look-up table -// TODO: should really be stored with the entity instead of being reconstructed -// TODO: could cache lazily, stored in the entity -// TODO: share work with R_SetUpAliasTransform - -// yaw - angle = currententity->angles[YAW]; - angle = angle * M_PI*2 / 360; - s = sin(angle); - c = cos(angle); - - temp1[0][0] = c; - temp1[0][1] = s; - temp1[0][2] = 0; - temp1[1][0] = -s; - temp1[1][1] = c; - temp1[1][2] = 0; - temp1[2][0] = 0; - temp1[2][1] = 0; - temp1[2][2] = 1; - - -// pitch - angle = currententity->angles[PITCH]; - angle = angle * M_PI*2 / 360; - s = sin(angle); - c = cos(angle); - - temp2[0][0] = c; - temp2[0][1] = 0; - temp2[0][2] = -s; - temp2[1][0] = 0; - temp2[1][1] = 1; - temp2[1][2] = 0; - temp2[2][0] = s; - temp2[2][1] = 0; - temp2[2][2] = c; - - R_ConcatRotations (temp2, temp1, temp3); - -// roll - angle = currententity->angles[ROLL]; - angle = angle * M_PI*2 / 360; - s = sin(angle); - c = cos(angle); - - temp1[0][0] = 1; - temp1[0][1] = 0; - temp1[0][2] = 0; - temp1[1][0] = 0; - temp1[1][1] = c; - temp1[1][2] = s; - temp1[2][0] = 0; - temp1[2][1] = -s; - temp1[2][2] = c; - - R_ConcatRotations (temp1, temp3, entity_rotation); - -// -// rotate modelorg and the transformation matrix -// - R_EntityRotate (modelorg); - R_EntityRotate (vpn); - R_EntityRotate (vright); - R_EntityRotate (vup); - - R_TransformFrustum (); -} - - -/* -================ -R_RecursiveClipBPoly -================ -*/ -void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) -{ - bedge_t *psideedges[2], *pnextedge, *ptedge; - int i, side, lastside; - float dist, frac, lastdist; - mplane_t *splitplane, tplane; - mvertex_t *pvert, *plastvert, *ptvert; - mnode_t *pn; - - psideedges[0] = psideedges[1] = NULL; - - makeclippededge = false; - -// transform the BSP plane into model space -// FIXME: cache these? - splitplane = pnode->plane; - tplane.dist = splitplane->dist - - DotProduct(r_entorigin, splitplane->normal); - tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); - tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); - tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); - -// clip edges to BSP plane - for ( ; pedges ; pedges = pnextedge) - { - pnextedge = pedges->pnext; - - // set the status for the last point as the previous point - // FIXME: cache this stuff somehow? - plastvert = pedges->v[0]; - lastdist = DotProduct (plastvert->position, tplane.normal) - - tplane.dist; - - if (lastdist > 0) - lastside = 0; - else - lastside = 1; - - pvert = pedges->v[1]; - - dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; - - if (dist > 0) - side = 0; - else - side = 1; - - if (side != lastside) - { - // clipped - if (numbverts >= MAX_BMODEL_VERTS) - return; - - // generate the clipped vertex - frac = lastdist / (lastdist - dist); - ptvert = &pbverts[numbverts++]; - ptvert->position[0] = plastvert->position[0] + - frac * (pvert->position[0] - - plastvert->position[0]); - ptvert->position[1] = plastvert->position[1] + - frac * (pvert->position[1] - - plastvert->position[1]); - ptvert->position[2] = plastvert->position[2] + - frac * (pvert->position[2] - - plastvert->position[2]); - - // split into two edges, one on each side, and remember entering - // and exiting points - // FIXME: share the clip edge by having a winding direction flag? - if (numbedges >= (MAX_BMODEL_EDGES - 1)) - { - Con_Printf ("Out of edges for bmodel\n"); - return; - } - - ptedge = &pbedges[numbedges]; - ptedge->pnext = psideedges[lastside]; - psideedges[lastside] = ptedge; - ptedge->v[0] = plastvert; - ptedge->v[1] = ptvert; - - ptedge = &pbedges[numbedges + 1]; - ptedge->pnext = psideedges[side]; - psideedges[side] = ptedge; - ptedge->v[0] = ptvert; - ptedge->v[1] = pvert; - - numbedges += 2; - - if (side == 0) - { - // entering for front, exiting for back - pfrontenter = ptvert; - makeclippededge = true; - } - else - { - pfrontexit = ptvert; - makeclippededge = true; - } - } - else - { - // add the edge to the appropriate side - pedges->pnext = psideedges[side]; - psideedges[side] = pedges; - } - } - -// if anything was clipped, reconstitute and add the edges along the clip -// plane to both sides (but in opposite directions) - if (makeclippededge) - { - if (numbedges >= (MAX_BMODEL_EDGES - 2)) - { - Con_Printf ("Out of edges for bmodel\n"); - return; - } - - ptedge = &pbedges[numbedges]; - ptedge->pnext = psideedges[0]; - psideedges[0] = ptedge; - ptedge->v[0] = pfrontexit; - ptedge->v[1] = pfrontenter; - - ptedge = &pbedges[numbedges + 1]; - ptedge->pnext = psideedges[1]; - psideedges[1] = ptedge; - ptedge->v[0] = pfrontenter; - ptedge->v[1] = pfrontexit; - - numbedges += 2; - } - -// draw or recurse further - for (i=0 ; i<2 ; i++) - { - if (psideedges[i]) - { - // draw if we've reached a non-solid leaf, done if all that's left is a - // solid leaf, and continue down the tree if it's not a leaf - pn = pnode->children[i]; - - // we're done with this branch if the node or leaf isn't in the PVS - if (pn->visframe == r_visframecount) - { - if (pn->contents < 0) - { - if (pn->contents != CONTENTS_SOLID) - { - r_currentbkey = ((mleaf_t *)pn)->key; - R_RenderBmodelFace (psideedges[i], psurf); - } - } - else - { - R_RecursiveClipBPoly (psideedges[i], pnode->children[i], - psurf); - } - } - } - } -} - - -/* -================ -R_DrawSolidClippedSubmodelPolygons -================ -*/ -void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) -{ - int i, j, lindex; - vec_t dot; - msurface_t *psurf; - int numsurfaces; - mplane_t *pplane; - mvertex_t bverts[MAX_BMODEL_VERTS]; - bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; - medge_t *pedge, *pedges; - -// FIXME: use bounding-box-based frustum clipping info? - - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - pedges = pmodel->edges; - - for (i=0 ; iplane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) - { - // FIXME: use bounding-box-based frustum clipping info? - - // copy the edges to bedges, flipping if necessary so always - // clockwise winding - // FIXME: if edges and vertices get caches, these assignments must move - // outside the loop, and overflow checking must be done here - pbverts = bverts; - pbedges = bedges; - numbverts = numbedges = 0; - - if (psurf->numedges > 0) - { - pbedge = &bedges[numbedges]; - numbedges += psurf->numedges; - - for (j=0 ; jnumedges ; j++) - { - lindex = pmodel->surfedges[psurf->firstedge+j]; - - if (lindex > 0) - { - pedge = &pedges[lindex]; - pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; - pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; - } - else - { - lindex = -lindex; - pedge = &pedges[lindex]; - pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; - pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; - } - - pbedge[j].pnext = &pbedge[j+1]; - } - - pbedge[j-1].pnext = NULL; // mark end of edges - - R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); - } - else - { - Sys_Error ("no edges in bmodel"); - } - } - } -} - - -/* -================ -R_DrawSubmodelPolygons -================ -*/ -void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) -{ - int i; - vec_t dot; - msurface_t *psurf; - int numsurfaces; - mplane_t *pplane; - -// FIXME: use bounding-box-based frustum clipping info? - - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - - for (i=0 ; iplane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) - { - r_currentkey = ((mleaf_t *)currententity->topnode)->key; - - // FIXME: use bounding-box-based frustum clipping info? - R_RenderFace (psurf, clipflags); - } - } -} - - -/* -================ -R_RecursiveWorldNode -================ -*/ -void R_RecursiveWorldNode (mnode_t *node, int clipflags) -{ - int i, c, side, *pindex; - vec3_t acceptpt, rejectpt; - mplane_t *plane; - msurface_t *surf, **mark; - mleaf_t *pleaf; - double d, dot; - - if (node->contents == CONTENTS_SOLID) - return; // solid - - if (node->visframe != r_visframecount) - return; - -// cull the clipping planes if not trivial accept -// FIXME: the compiler is doing a lousy job of optimizing here; it could be -// twice as fast in ASM - if (clipflags) - { - for (i=0 ; i<4 ; i++) - { - if (! (clipflags & (1<minmaxs[pindex[0]]; - rejectpt[1] = (float)node->minmaxs[pindex[1]]; - rejectpt[2] = (float)node->minmaxs[pindex[2]]; - - d = DotProduct (rejectpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d <= 0) - return; - - acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; - acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; - acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; - - d = DotProduct (acceptpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d >= 0) - clipflags &= ~(1<contents < 0) - { - pleaf = (mleaf_t *)node; - - mark = pleaf->firstmarksurface; - c = pleaf->nummarksurfaces; - - if (c) - { - do - { - (*mark)->visframe = r_framecount; - mark++; - } while (--c); - } - - // deal with model fragments in this leaf - if (pleaf->efrags) - { - R_StoreEfrags (&pleaf->efrags); - } - - pleaf->key = r_currentkey; - r_currentkey++; // all bmodels in a leaf share the same key - } - else - { - // node is just a decision point, so go down the apropriate sides - - // find which side of the node we are on - plane = node->plane; - - switch (plane->type) - { - case PLANE_X: - dot = modelorg[0] - plane->dist; - break; - case PLANE_Y: - dot = modelorg[1] - plane->dist; - break; - case PLANE_Z: - dot = modelorg[2] - plane->dist; - break; - default: - dot = DotProduct (modelorg, plane->normal) - plane->dist; - break; - } - - if (dot >= 0) - side = 0; - else - side = 1; - - // recurse down the children, front side first - R_RecursiveWorldNode (node->children[side], clipflags); - - // draw stuff - c = node->numsurfaces; - - if (c) - { - surf = cl.worldmodel->surfaces + node->firstsurface; - - if (dot < -BACKFACE_EPSILON) - { - do - { - if ((surf->flags & SURF_PLANEBACK) && - (surf->visframe == r_framecount)) - { - if (r_drawpolys) - { - if (r_worldpolysbacktofront) - { - if (numbtofpolys < MAX_BTOFPOLYS) - { - pbtofpolys[numbtofpolys].clipflags = - clipflags; - pbtofpolys[numbtofpolys].psurf = surf; - numbtofpolys++; - } - } - else - { - R_RenderPoly (surf, clipflags); - } - } - else - { - R_RenderFace (surf, clipflags); - } - } - - surf++; - } while (--c); - } - else if (dot > BACKFACE_EPSILON) - { - do - { - if (!(surf->flags & SURF_PLANEBACK) && - (surf->visframe == r_framecount)) - { - if (r_drawpolys) - { - if (r_worldpolysbacktofront) - { - if (numbtofpolys < MAX_BTOFPOLYS) - { - pbtofpolys[numbtofpolys].clipflags = - clipflags; - pbtofpolys[numbtofpolys].psurf = surf; - numbtofpolys++; - } - } - else - { - R_RenderPoly (surf, clipflags); - } - } - else - { - R_RenderFace (surf, clipflags); - } - } - - surf++; - } while (--c); - } - - // all surfaces on the same node share the same sequence number - r_currentkey++; - } - - // recurse down the back side - R_RecursiveWorldNode (node->children[!side], clipflags); - } -} - - - -/* -================ -R_RenderWorld -================ -*/ -void R_RenderWorld (void) -{ - int i; - model_t *clmodel; - btofpoly_t btofpolys[MAX_BTOFPOLYS]; - - pbtofpolys = btofpolys; - - currententity = &cl_entities[0]; - VectorCopy (r_origin, modelorg); - clmodel = currententity->model; - r_pcurrentvertbase = clmodel->vertexes; - - R_RecursiveWorldNode (clmodel->nodes, 15); - -// if the driver wants the polygons back to front, play the visible ones back -// in that order - if (r_worldpolysbacktofront) - { - for (i=numbtofpolys-1 ; i>=0 ; i--) - { - R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); - } - } -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_bsp.c + +#include "quakedef.h" +#include "r_local.h" + +// +// current entity info +// +qboolean insubmodel; +entity_t *currententity; +vec3_t modelorg, base_modelorg; + // modelorg is the viewpoint reletive to + // the currently rendering entity +vec3_t r_entorigin; // the currently rendering entity in world + // coordinates + +float entity_rotation[3][3]; + +vec3_t r_worldmodelorg; + +int r_currentbkey; + +typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; + +#define MAX_BMODEL_VERTS 500 // 6K +#define MAX_BMODEL_EDGES 1000 // 12K + +static mvertex_t *pbverts; +static bedge_t *pbedges; +static int numbverts, numbedges; + +static mvertex_t *pfrontenter, *pfrontexit; + +static qboolean makeclippededge; + + +//=========================================================================== + +/* +================ +R_EntityRotate +================ +*/ +void R_EntityRotate (vec3_t vec) +{ + vec3_t tvec; + + VectorCopy (vec, tvec); + vec[0] = DotProduct (entity_rotation[0], tvec); + vec[1] = DotProduct (entity_rotation[1], tvec); + vec[2] = DotProduct (entity_rotation[2], tvec); +} + + +/* +================ +R_RotateBmodel +================ +*/ +void R_RotateBmodel (void) +{ + float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3]; + +// TODO: should use a look-up table +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: could cache lazily, stored in the entity +// TODO: share work with R_SetUpAliasTransform + +// yaw + angle = currententity->angles[YAW]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp1[0][0] = c; + temp1[0][1] = s; + temp1[0][2] = 0; + temp1[1][0] = -s; + temp1[1][1] = c; + temp1[1][2] = 0; + temp1[2][0] = 0; + temp1[2][1] = 0; + temp1[2][2] = 1; + + +// pitch + angle = currententity->angles[PITCH]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp2[0][0] = c; + temp2[0][1] = 0; + temp2[0][2] = -s; + temp2[1][0] = 0; + temp2[1][1] = 1; + temp2[1][2] = 0; + temp2[2][0] = s; + temp2[2][1] = 0; + temp2[2][2] = c; + + R_ConcatRotations (temp2, temp1, temp3); + +// roll + angle = currententity->angles[ROLL]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp1[0][0] = 1; + temp1[0][1] = 0; + temp1[0][2] = 0; + temp1[1][0] = 0; + temp1[1][1] = c; + temp1[1][2] = s; + temp1[2][0] = 0; + temp1[2][1] = -s; + temp1[2][2] = c; + + R_ConcatRotations (temp1, temp3, entity_rotation); + +// +// rotate modelorg and the transformation matrix +// + R_EntityRotate (modelorg); + R_EntityRotate (vpn); + R_EntityRotate (vright); + R_EntityRotate (vup); + + R_TransformFrustum (); +} + + +/* +================ +R_RecursiveClipBPoly +================ +*/ +void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) +{ + bedge_t *psideedges[2], *pnextedge, *ptedge; + int i, side, lastside; + float dist, frac, lastdist; + mplane_t *splitplane, tplane; + mvertex_t *pvert, *plastvert, *ptvert; + mnode_t *pn; + + psideedges[0] = psideedges[1] = NULL; + + makeclippededge = false; + +// transform the BSP plane into model space +// FIXME: cache these? + splitplane = pnode->plane; + tplane.dist = splitplane->dist - + DotProduct(r_entorigin, splitplane->normal); + tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); + tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); + tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); + +// clip edges to BSP plane + for ( ; pedges ; pedges = pnextedge) + { + pnextedge = pedges->pnext; + + // set the status for the last point as the previous point + // FIXME: cache this stuff somehow? + plastvert = pedges->v[0]; + lastdist = DotProduct (plastvert->position, tplane.normal) - + tplane.dist; + + if (lastdist > 0) + lastside = 0; + else + lastside = 1; + + pvert = pedges->v[1]; + + dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; + + if (dist > 0) + side = 0; + else + side = 1; + + if (side != lastside) + { + // clipped + if (numbverts >= MAX_BMODEL_VERTS) + return; + + // generate the clipped vertex + frac = lastdist / (lastdist - dist); + ptvert = &pbverts[numbverts++]; + ptvert->position[0] = plastvert->position[0] + + frac * (pvert->position[0] - + plastvert->position[0]); + ptvert->position[1] = plastvert->position[1] + + frac * (pvert->position[1] - + plastvert->position[1]); + ptvert->position[2] = plastvert->position[2] + + frac * (pvert->position[2] - + plastvert->position[2]); + + // split into two edges, one on each side, and remember entering + // and exiting points + // FIXME: share the clip edge by having a winding direction flag? + if (numbedges >= (MAX_BMODEL_EDGES - 1)) + { + Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[lastside]; + psideedges[lastside] = ptedge; + ptedge->v[0] = plastvert; + ptedge->v[1] = ptvert; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[side]; + psideedges[side] = ptedge; + ptedge->v[0] = ptvert; + ptedge->v[1] = pvert; + + numbedges += 2; + + if (side == 0) + { + // entering for front, exiting for back + pfrontenter = ptvert; + makeclippededge = true; + } + else + { + pfrontexit = ptvert; + makeclippededge = true; + } + } + else + { + // add the edge to the appropriate side + pedges->pnext = psideedges[side]; + psideedges[side] = pedges; + } + } + +// if anything was clipped, reconstitute and add the edges along the clip +// plane to both sides (but in opposite directions) + if (makeclippededge) + { + if (numbedges >= (MAX_BMODEL_EDGES - 2)) + { + Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[0]; + psideedges[0] = ptedge; + ptedge->v[0] = pfrontexit; + ptedge->v[1] = pfrontenter; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[1]; + psideedges[1] = ptedge; + ptedge->v[0] = pfrontenter; + ptedge->v[1] = pfrontexit; + + numbedges += 2; + } + +// draw or recurse further + for (i=0 ; i<2 ; i++) + { + if (psideedges[i]) + { + // draw if we've reached a non-solid leaf, done if all that's left is a + // solid leaf, and continue down the tree if it's not a leaf + pn = pnode->children[i]; + + // we're done with this branch if the node or leaf isn't in the PVS + if (pn->visframe == r_visframecount) + { + if (pn->contents < 0) + { + if (pn->contents != CONTENTS_SOLID) + { + r_currentbkey = ((mleaf_t *)pn)->key; + R_RenderBmodelFace (psideedges[i], psurf); + } + } + else + { + R_RecursiveClipBPoly (psideedges[i], pnode->children[i], + psurf); + } + } + } + } +} + + +/* +================ +R_DrawSolidClippedSubmodelPolygons +================ +*/ +void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) +{ + int i, j, lindex; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + mvertex_t bverts[MAX_BMODEL_VERTS]; + bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; + medge_t *pedge, *pedges; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + pedges = pmodel->edges; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + // FIXME: use bounding-box-based frustum clipping info? + + // copy the edges to bedges, flipping if necessary so always + // clockwise winding + // FIXME: if edges and vertices get caches, these assignments must move + // outside the loop, and overflow checking must be done here + pbverts = bverts; + pbedges = bedges; + numbverts = numbedges = 0; + + if (psurf->numedges > 0) + { + pbedge = &bedges[numbedges]; + numbedges += psurf->numedges; + + for (j=0 ; jnumedges ; j++) + { + lindex = pmodel->surfedges[psurf->firstedge+j]; + + if (lindex > 0) + { + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; + } + else + { + lindex = -lindex; + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; + } + + pbedge[j].pnext = &pbedge[j+1]; + } + + pbedge[j-1].pnext = NULL; // mark end of edges + + R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); + } + else + { + Sys_Error ("no edges in bmodel"); + } + } + } +} + + +/* +================ +R_DrawSubmodelPolygons +================ +*/ +void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) +{ + int i; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + r_currentkey = ((mleaf_t *)currententity->topnode)->key; + + // FIXME: use bounding-box-based frustum clipping info? + R_RenderFace (psurf, clipflags); + } + } +} + + +/* +================ +R_RecursiveWorldNode +================ +*/ +void R_RecursiveWorldNode (mnode_t *node, int clipflags) +{ + int i, c, side, *pindex; + vec3_t acceptpt, rejectpt; + mplane_t *plane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + double d, dot; + + if (node->contents == CONTENTS_SOLID) + return; // solid + + if (node->visframe != r_visframecount) + return; + +// cull the clipping planes if not trivial accept +// FIXME: the compiler is doing a lousy job of optimizing here; it could be +// twice as fast in ASM + if (clipflags) + { + for (i=0 ; i<4 ; i++) + { + if (! (clipflags & (1<minmaxs[pindex[0]]; + rejectpt[1] = (float)node->minmaxs[pindex[1]]; + rejectpt[2] = (float)node->minmaxs[pindex[2]]; + + d = DotProduct (rejectpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + return; + + acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; + acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; + acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; + + d = DotProduct (acceptpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d >= 0) + clipflags &= ~(1<contents < 0) + { + pleaf = (mleaf_t *)node; + + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + if (c) + { + do + { + (*mark)->visframe = r_framecount; + mark++; + } while (--c); + } + + // deal with model fragments in this leaf + if (pleaf->efrags) + { + R_StoreEfrags (&pleaf->efrags); + } + + pleaf->key = r_currentkey; + r_currentkey++; // all bmodels in a leaf share the same key + } + else + { + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + plane = node->plane; + + switch (plane->type) + { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + side = 0; + else + side = 1; + + // recurse down the children, front side first + R_RecursiveWorldNode (node->children[side], clipflags); + + // draw stuff + c = node->numsurfaces; + + if (c) + { + surf = cl.worldmodel->surfaces + node->firstsurface; + + if (dot < -BACKFACE_EPSILON) + { + do + { + if ((surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) + { + if (r_drawpolys) + { + if (r_worldpolysbacktofront) + { + if (numbtofpolys < MAX_BTOFPOLYS) + { + pbtofpolys[numbtofpolys].clipflags = + clipflags; + pbtofpolys[numbtofpolys].psurf = surf; + numbtofpolys++; + } + } + else + { + R_RenderPoly (surf, clipflags); + } + } + else + { + R_RenderFace (surf, clipflags); + } + } + + surf++; + } while (--c); + } + else if (dot > BACKFACE_EPSILON) + { + do + { + if (!(surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) + { + if (r_drawpolys) + { + if (r_worldpolysbacktofront) + { + if (numbtofpolys < MAX_BTOFPOLYS) + { + pbtofpolys[numbtofpolys].clipflags = + clipflags; + pbtofpolys[numbtofpolys].psurf = surf; + numbtofpolys++; + } + } + else + { + R_RenderPoly (surf, clipflags); + } + } + else + { + R_RenderFace (surf, clipflags); + } + } + + surf++; + } while (--c); + } + + // all surfaces on the same node share the same sequence number + r_currentkey++; + } + + // recurse down the back side + R_RecursiveWorldNode (node->children[!side], clipflags); + } +} + + + +/* +================ +R_RenderWorld +================ +*/ +void R_RenderWorld (void) +{ + int i; + model_t *clmodel; + btofpoly_t btofpolys[MAX_BTOFPOLYS]; + + pbtofpolys = btofpolys; + + currententity = &cl_entities[0]; + VectorCopy (r_origin, modelorg); + clmodel = currententity->model; + r_pcurrentvertbase = clmodel->vertexes; + + R_RecursiveWorldNode (clmodel->nodes, 15); + +// if the driver wants the polygons back to front, play the visible ones back +// in that order + if (r_worldpolysbacktofront) + { + for (i=numbtofpolys-1 ; i>=0 ; i--) + { + R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); + } + } +} + + diff --git a/WinQuake/r_draw.c b/WinQuake/r_draw.c index 2ccf316..af96efe 100644 --- a/WinQuake/r_draw.c +++ b/WinQuake/r_draw.c @@ -1,908 +1,908 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_draw.c - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" // FIXME: shouldn't need to include this - -#define MAXLEFTCLIPEDGES 100 - -// !!! if these are changed, they must be changed in asm_draw.h too !!! -#define FULLY_CLIPPED_CACHED 0x80000000 -#define FRAMECOUNT_MASK 0x7FFFFFFF - -unsigned int cacheoffset; - -int c_faceclip; // number of faces clipped - -zpointdesc_t r_zpointdesc; - -polydesc_t r_polydesc; - - - -clipplane_t *entity_clipplanes; -clipplane_t view_clipplanes[4]; -clipplane_t world_clipplanes[16]; - -medge_t *r_pedge; - -qboolean r_leftclipped, r_rightclipped; -static qboolean makeleftedge, makerightedge; -qboolean r_nearzionly; - -int sintable[SIN_BUFFER_SIZE]; -int intsintable[SIN_BUFFER_SIZE]; - -mvertex_t r_leftenter, r_leftexit; -mvertex_t r_rightenter, r_rightexit; - -typedef struct -{ - float u,v; - int ceilv; -} evert_t; - -int r_emitted; -float r_nearzi; -float r_u1, r_v1, r_lzi1; -int r_ceilv1; - -qboolean r_lastvertvalid; - - -#if !id386 - -/* -================ -R_EmitEdge -================ -*/ -void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) -{ - edge_t *edge, *pcheck; - int u_check; - float u, u_step; - vec3_t local, transformed; - float *world; - int v, v2, ceilv0; - float scale, lzi0, u0, v0; - int side; - - if (r_lastvertvalid) - { - u0 = r_u1; - v0 = r_v1; - lzi0 = r_lzi1; - ceilv0 = r_ceilv1; - } - else - { - world = &pv0->position[0]; - - // transform and project - VectorSubtract (world, modelorg, local); - TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - lzi0 = 1.0 / transformed[2]; - - // FIXME: build x/yscale into transform? - scale = xscale * lzi0; - u0 = (xcenter + scale*transformed[0]); - if (u0 < r_refdef.fvrectx_adj) - u0 = r_refdef.fvrectx_adj; - if (u0 > r_refdef.fvrectright_adj) - u0 = r_refdef.fvrectright_adj; - - scale = yscale * lzi0; - v0 = (ycenter - scale*transformed[1]); - if (v0 < r_refdef.fvrecty_adj) - v0 = r_refdef.fvrecty_adj; - if (v0 > r_refdef.fvrectbottom_adj) - v0 = r_refdef.fvrectbottom_adj; - - ceilv0 = (int) ceil(v0); - } - - world = &pv1->position[0]; - -// transform and project - VectorSubtract (world, modelorg, local); - TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - r_lzi1 = 1.0 / transformed[2]; - - scale = xscale * r_lzi1; - r_u1 = (xcenter + scale*transformed[0]); - if (r_u1 < r_refdef.fvrectx_adj) - r_u1 = r_refdef.fvrectx_adj; - if (r_u1 > r_refdef.fvrectright_adj) - r_u1 = r_refdef.fvrectright_adj; - - scale = yscale * r_lzi1; - r_v1 = (ycenter - scale*transformed[1]); - if (r_v1 < r_refdef.fvrecty_adj) - r_v1 = r_refdef.fvrecty_adj; - if (r_v1 > r_refdef.fvrectbottom_adj) - r_v1 = r_refdef.fvrectbottom_adj; - - if (r_lzi1 > lzi0) - lzi0 = r_lzi1; - - if (lzi0 > r_nearzi) // for mipmap finding - r_nearzi = lzi0; - -// for right edges, all we want is the effect on 1/z - if (r_nearzionly) - return; - - r_emitted = 1; - - r_ceilv1 = (int) ceil(r_v1); - - -// create the edge - if (ceilv0 == r_ceilv1) - { - // we cache unclipped horizontal edges as fully clipped - if (cacheoffset != 0x7FFFFFFF) - { - cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); - } - - return; // horizontal edge - } - - side = ceilv0 > r_ceilv1; - - edge = edge_p++; - - edge->owner = r_pedge; - - edge->nearzi = lzi0; - - if (side == 0) - { - // trailing edge (go from p1 to p2) - v = ceilv0; - v2 = r_ceilv1 - 1; - - edge->surfs[0] = surface_p - surfaces; - edge->surfs[1] = 0; - - u_step = ((r_u1 - u0) / (r_v1 - v0)); - u = u0 + ((float)v - v0) * u_step; - } - else - { - // leading edge (go from p2 to p1) - v2 = ceilv0 - 1; - v = r_ceilv1; - - edge->surfs[0] = 0; - edge->surfs[1] = surface_p - surfaces; - - u_step = ((u0 - r_u1) / (v0 - r_v1)); - u = r_u1 + ((float)v - r_v1) * u_step; - } - - edge->u_step = u_step*0x100000; - edge->u = u*0x100000 + 0xFFFFF; - -// we need to do this to avoid stepping off the edges if a very nearly -// horizontal edge is less than epsilon above a scan, and numeric error causes -// it to incorrectly extend to the scan, and the extension of the line goes off -// the edge of the screen -// FIXME: is this actually needed? - if (edge->u < r_refdef.vrect_x_adj_shift20) - edge->u = r_refdef.vrect_x_adj_shift20; - if (edge->u > r_refdef.vrectright_adj_shift20) - edge->u = r_refdef.vrectright_adj_shift20; - -// -// sort the edge in normally -// - u_check = edge->u; - if (edge->surfs[0]) - u_check++; // sort trailers after leaders - - if (!newedges[v] || newedges[v]->u >= u_check) - { - edge->next = newedges[v]; - newedges[v] = edge; - } - else - { - pcheck = newedges[v]; - while (pcheck->next && pcheck->next->u < u_check) - pcheck = pcheck->next; - edge->next = pcheck->next; - pcheck->next = edge; - } - - edge->nextremove = removeedges[v2]; - removeedges[v2] = edge; -} - - -/* -================ -R_ClipEdge -================ -*/ -void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) -{ - float d0, d1, f; - mvertex_t clipvert; - - if (clip) - { - do - { - d0 = DotProduct (pv0->position, clip->normal) - clip->dist; - d1 = DotProduct (pv1->position, clip->normal) - clip->dist; - - if (d0 >= 0) - { - // point 0 is unclipped - if (d1 >= 0) - { - // both points are unclipped - continue; - } - - // only point 1 is clipped - - // we don't cache clipped edges - cacheoffset = 0x7FFFFFFF; - - f = d0 / (d0 - d1); - clipvert.position[0] = pv0->position[0] + - f * (pv1->position[0] - pv0->position[0]); - clipvert.position[1] = pv0->position[1] + - f * (pv1->position[1] - pv0->position[1]); - clipvert.position[2] = pv0->position[2] + - f * (pv1->position[2] - pv0->position[2]); - - if (clip->leftedge) - { - r_leftclipped = true; - r_leftexit = clipvert; - } - else if (clip->rightedge) - { - r_rightclipped = true; - r_rightexit = clipvert; - } - - R_ClipEdge (pv0, &clipvert, clip->next); - return; - } - else - { - // point 0 is clipped - if (d1 < 0) - { - // both points are clipped - // we do cache fully clipped edges - if (!r_leftclipped) - cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); - return; - } - - // only point 0 is clipped - r_lastvertvalid = false; - - // we don't cache partially clipped edges - cacheoffset = 0x7FFFFFFF; - - f = d0 / (d0 - d1); - clipvert.position[0] = pv0->position[0] + - f * (pv1->position[0] - pv0->position[0]); - clipvert.position[1] = pv0->position[1] + - f * (pv1->position[1] - pv0->position[1]); - clipvert.position[2] = pv0->position[2] + - f * (pv1->position[2] - pv0->position[2]); - - if (clip->leftedge) - { - r_leftclipped = true; - r_leftenter = clipvert; - } - else if (clip->rightedge) - { - r_rightclipped = true; - r_rightenter = clipvert; - } - - R_ClipEdge (&clipvert, pv1, clip->next); - return; - } - } while ((clip = clip->next) != NULL); - } - -// add the edge - R_EmitEdge (pv0, pv1); -} - -#endif // !id386 - - -/* -================ -R_EmitCachedEdge -================ -*/ -void R_EmitCachedEdge (void) -{ - edge_t *pedge_t; - - pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset); - - if (!pedge_t->surfs[0]) - pedge_t->surfs[0] = surface_p - surfaces; - else - pedge_t->surfs[1] = surface_p - surfaces; - - if (pedge_t->nearzi > r_nearzi) // for mipmap finding - r_nearzi = pedge_t->nearzi; - - r_emitted = 1; -} - - -/* -================ -R_RenderFace -================ -*/ -void R_RenderFace (msurface_t *fa, int clipflags) -{ - int i, lindex; - unsigned mask; - mplane_t *pplane; - float distinv; - vec3_t p_normal; - medge_t *pedges, tedge; - clipplane_t *pclip; - -// skip out if no more surfs - if ((surface_p) >= surf_max) - { - r_outofsurfaces++; - return; - } - -// ditto if not enough edges left, or switch to auxedges if possible - if ((edge_p + fa->numedges + 4) >= edge_max) - { - r_outofedges += fa->numedges; - return; - } - - c_faceclip++; - -// set up clip planes - pclip = NULL; - - for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) - { - if (clipflags & mask) - { - view_clipplanes[i].next = pclip; - pclip = &view_clipplanes[i]; - } - } - -// push the edges through - r_emitted = 0; - r_nearzi = 0; - r_nearzionly = false; - makeleftedge = makerightedge = false; - pedges = currententity->model->edges; - r_lastvertvalid = false; - - for (i=0 ; inumedges ; i++) - { - lindex = currententity->model->surfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - - // if the edge is cached, we can just reuse the edge - if (!insubmodel) - { - if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) - { - if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - r_framecount) - { - r_lastvertvalid = false; - continue; - } - } - else - { - if ((((unsigned long)edge_p - (unsigned long)r_edges) > - r_pedge->cachededgeoffset) && - (((edge_t *)((unsigned long)r_edges + - r_pedge->cachededgeoffset))->owner == r_pedge)) - { - R_EmitCachedEdge (); - r_lastvertvalid = false; - continue; - } - } - } - - // assume it's cacheable - cacheoffset = (byte *)edge_p - (byte *)r_edges; - r_leftclipped = r_rightclipped = false; - R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], - &r_pcurrentvertbase[r_pedge->v[1]], - pclip); - r_pedge->cachededgeoffset = cacheoffset; - - if (r_leftclipped) - makeleftedge = true; - if (r_rightclipped) - makerightedge = true; - r_lastvertvalid = true; - } - else - { - lindex = -lindex; - r_pedge = &pedges[lindex]; - // if the edge is cached, we can just reuse the edge - if (!insubmodel) - { - if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) - { - if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - r_framecount) - { - r_lastvertvalid = false; - continue; - } - } - else - { - // it's cached if the cached edge is valid and is owned - // by this medge_t - if ((((unsigned long)edge_p - (unsigned long)r_edges) > - r_pedge->cachededgeoffset) && - (((edge_t *)((unsigned long)r_edges + - r_pedge->cachededgeoffset))->owner == r_pedge)) - { - R_EmitCachedEdge (); - r_lastvertvalid = false; - continue; - } - } - } - - // assume it's cacheable - cacheoffset = (byte *)edge_p - (byte *)r_edges; - r_leftclipped = r_rightclipped = false; - R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], - &r_pcurrentvertbase[r_pedge->v[0]], - pclip); - r_pedge->cachededgeoffset = cacheoffset; - - if (r_leftclipped) - makeleftedge = true; - if (r_rightclipped) - makerightedge = true; - r_lastvertvalid = true; - } - } - -// if there was a clip off the left edge, add that edge too -// FIXME: faster to do in screen space? -// FIXME: share clipped edges? - if (makeleftedge) - { - r_pedge = &tedge; - r_lastvertvalid = false; - R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); - } - -// if there was a clip off the right edge, get the right r_nearzi - if (makerightedge) - { - r_pedge = &tedge; - r_lastvertvalid = false; - r_nearzionly = true; - R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); - } - -// if no edges made it out, return without posting the surface - if (!r_emitted) - return; - - r_polycount++; - - surface_p->data = (void *)fa; - surface_p->nearzi = r_nearzi; - surface_p->flags = fa->flags; - surface_p->insubmodel = insubmodel; - surface_p->spanstate = 0; - surface_p->entity = currententity; - surface_p->key = r_currentkey++; - surface_p->spans = NULL; - - pplane = fa->plane; -// FIXME: cache this? - TransformVector (pplane->normal, p_normal); -// FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); - - surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; - surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; - surface_p->d_ziorigin = p_normal[2] * distinv - - xcenter * surface_p->d_zistepu - - ycenter * surface_p->d_zistepv; - -//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); - surface_p++; -} - - -/* -================ -R_RenderBmodelFace -================ -*/ -void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) -{ - int i; - unsigned mask; - mplane_t *pplane; - float distinv; - vec3_t p_normal; - medge_t tedge; - clipplane_t *pclip; - -// skip out if no more surfs - if (surface_p >= surf_max) - { - r_outofsurfaces++; - return; - } - -// ditto if not enough edges left, or switch to auxedges if possible - if ((edge_p + psurf->numedges + 4) >= edge_max) - { - r_outofedges += psurf->numedges; - return; - } - - c_faceclip++; - -// this is a dummy to give the caching mechanism someplace to write to - r_pedge = &tedge; - -// set up clip planes - pclip = NULL; - - for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) - { - if (r_clipflags & mask) - { - view_clipplanes[i].next = pclip; - pclip = &view_clipplanes[i]; - } - } - -// push the edges through - r_emitted = 0; - r_nearzi = 0; - r_nearzionly = false; - makeleftedge = makerightedge = false; -// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching -// can be used? - r_lastvertvalid = false; - - for ( ; pedges ; pedges = pedges->pnext) - { - r_leftclipped = r_rightclipped = false; - R_ClipEdge (pedges->v[0], pedges->v[1], pclip); - - if (r_leftclipped) - makeleftedge = true; - if (r_rightclipped) - makerightedge = true; - } - -// if there was a clip off the left edge, add that edge too -// FIXME: faster to do in screen space? -// FIXME: share clipped edges? - if (makeleftedge) - { - r_pedge = &tedge; - R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); - } - -// if there was a clip off the right edge, get the right r_nearzi - if (makerightedge) - { - r_pedge = &tedge; - r_nearzionly = true; - R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); - } - -// if no edges made it out, return without posting the surface - if (!r_emitted) - return; - - r_polycount++; - - surface_p->data = (void *)psurf; - surface_p->nearzi = r_nearzi; - surface_p->flags = psurf->flags; - surface_p->insubmodel = true; - surface_p->spanstate = 0; - surface_p->entity = currententity; - surface_p->key = r_currentbkey; - surface_p->spans = NULL; - - pplane = psurf->plane; -// FIXME: cache this? - TransformVector (pplane->normal, p_normal); -// FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); - - surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; - surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; - surface_p->d_ziorigin = p_normal[2] * distinv - - xcenter * surface_p->d_zistepu - - ycenter * surface_p->d_zistepv; - -//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); - surface_p++; -} - - -/* -================ -R_RenderPoly -================ -*/ -void R_RenderPoly (msurface_t *fa, int clipflags) -{ - int i, lindex, lnumverts, s_axis, t_axis; - float dist, lastdist, lzi, scale, u, v, frac; - unsigned mask; - vec3_t local, transformed; - clipplane_t *pclip; - medge_t *pedges; - mplane_t *pplane; - mvertex_t verts[2][100]; //FIXME: do real number - polyvert_t pverts[100]; //FIXME: do real number, safely - int vertpage, newverts, newpage, lastvert; - qboolean visible; - -// FIXME: clean this up and make it faster -// FIXME: guard against running out of vertices - - s_axis = t_axis = 0; // keep compiler happy - -// set up clip planes - pclip = NULL; - - for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) - { - if (clipflags & mask) - { - view_clipplanes[i].next = pclip; - pclip = &view_clipplanes[i]; - } - } - -// reconstruct the polygon -// FIXME: these should be precalculated and loaded off disk - pedges = currententity->model->edges; - lnumverts = fa->numedges; - vertpage = 0; - - for (i=0 ; imodel->surfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]]; - } - else - { - r_pedge = &pedges[-lindex]; - verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]]; - } - } - -// clip the polygon, done if not visible - while (pclip) - { - lastvert = lnumverts - 1; - lastdist = DotProduct (verts[vertpage][lastvert].position, - pclip->normal) - pclip->dist; - - visible = false; - newverts = 0; - newpage = vertpage ^ 1; - - for (i=0 ; inormal) - - pclip->dist; - - if ((lastdist > 0) != (dist > 0)) - { - frac = dist / (dist - lastdist); - verts[newpage][newverts].position[0] = - verts[vertpage][i].position[0] + - ((verts[vertpage][lastvert].position[0] - - verts[vertpage][i].position[0]) * frac); - verts[newpage][newverts].position[1] = - verts[vertpage][i].position[1] + - ((verts[vertpage][lastvert].position[1] - - verts[vertpage][i].position[1]) * frac); - verts[newpage][newverts].position[2] = - verts[vertpage][i].position[2] + - ((verts[vertpage][lastvert].position[2] - - verts[vertpage][i].position[2]) * frac); - newverts++; - } - - if (dist >= 0) - { - verts[newpage][newverts] = verts[vertpage][i]; - newverts++; - visible = true; - } - - lastvert = i; - lastdist = dist; - } - - if (!visible || (newverts < 3)) - return; - - lnumverts = newverts; - vertpage ^= 1; - pclip = pclip->next; - } - -// transform and project, remembering the z values at the vertices and -// r_nearzi, and extract the s and t coordinates at the vertices - pplane = fa->plane; - switch (pplane->type) - { - case PLANE_X: - case PLANE_ANYX: - s_axis = 1; - t_axis = 2; - break; - case PLANE_Y: - case PLANE_ANYY: - s_axis = 0; - t_axis = 2; - break; - case PLANE_Z: - case PLANE_ANYZ: - s_axis = 0; - t_axis = 1; - break; - } - - r_nearzi = 0; - - for (i=0 ; i r_nearzi) // for mipmap finding - r_nearzi = lzi; - - // FIXME: build x/yscale into transform? - scale = xscale * lzi; - u = (xcenter + scale*transformed[0]); - if (u < r_refdef.fvrectx_adj) - u = r_refdef.fvrectx_adj; - if (u > r_refdef.fvrectright_adj) - u = r_refdef.fvrectright_adj; - - scale = yscale * lzi; - v = (ycenter - scale*transformed[1]); - if (v < r_refdef.fvrecty_adj) - v = r_refdef.fvrecty_adj; - if (v > r_refdef.fvrectbottom_adj) - v = r_refdef.fvrectbottom_adj; - - pverts[i].u = u; - pverts[i].v = v; - pverts[i].zi = lzi; - pverts[i].s = verts[vertpage][i].position[s_axis]; - pverts[i].t = verts[vertpage][i].position[t_axis]; - } - -// build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z -// for each vertex - r_polydesc.numverts = lnumverts; - r_polydesc.nearzi = r_nearzi; - r_polydesc.pcurrentface = fa; - r_polydesc.pverts = pverts; - -// draw the polygon - D_DrawPoly (); -} - - -/* -================ -R_ZDrawSubmodelPolys -================ -*/ -void R_ZDrawSubmodelPolys (model_t *pmodel) -{ - int i, numsurfaces; - msurface_t *psurf; - float dot; - mplane_t *pplane; - - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - - for (i=0 ; iplane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) - { - // FIXME: use bounding-box-based frustum clipping info? - R_RenderPoly (psurf, 15); - } - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// r_draw.c + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" // FIXME: shouldn't need to include this + +#define MAXLEFTCLIPEDGES 100 + +// !!! if these are changed, they must be changed in asm_draw.h too !!! +#define FULLY_CLIPPED_CACHED 0x80000000 +#define FRAMECOUNT_MASK 0x7FFFFFFF + +unsigned int cacheoffset; + +int c_faceclip; // number of faces clipped + +zpointdesc_t r_zpointdesc; + +polydesc_t r_polydesc; + + + +clipplane_t *entity_clipplanes; +clipplane_t view_clipplanes[4]; +clipplane_t world_clipplanes[16]; + +medge_t *r_pedge; + +qboolean r_leftclipped, r_rightclipped; +static qboolean makeleftedge, makerightedge; +qboolean r_nearzionly; + +int sintable[SIN_BUFFER_SIZE]; +int intsintable[SIN_BUFFER_SIZE]; + +mvertex_t r_leftenter, r_leftexit; +mvertex_t r_rightenter, r_rightexit; + +typedef struct +{ + float u,v; + int ceilv; +} evert_t; + +int r_emitted; +float r_nearzi; +float r_u1, r_v1, r_lzi1; +int r_ceilv1; + +qboolean r_lastvertvalid; + + +#if !id386 + +/* +================ +R_EmitEdge +================ +*/ +void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) +{ + edge_t *edge, *pcheck; + int u_check; + float u, u_step; + vec3_t local, transformed; + float *world; + int v, v2, ceilv0; + float scale, lzi0, u0, v0; + int side; + + if (r_lastvertvalid) + { + u0 = r_u1; + v0 = r_v1; + lzi0 = r_lzi1; + ceilv0 = r_ceilv1; + } + else + { + world = &pv0->position[0]; + + // transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + lzi0 = 1.0 / transformed[2]; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi0; + u0 = (xcenter + scale*transformed[0]); + if (u0 < r_refdef.fvrectx_adj) + u0 = r_refdef.fvrectx_adj; + if (u0 > r_refdef.fvrectright_adj) + u0 = r_refdef.fvrectright_adj; + + scale = yscale * lzi0; + v0 = (ycenter - scale*transformed[1]); + if (v0 < r_refdef.fvrecty_adj) + v0 = r_refdef.fvrecty_adj; + if (v0 > r_refdef.fvrectbottom_adj) + v0 = r_refdef.fvrectbottom_adj; + + ceilv0 = (int) ceil(v0); + } + + world = &pv1->position[0]; + +// transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + r_lzi1 = 1.0 / transformed[2]; + + scale = xscale * r_lzi1; + r_u1 = (xcenter + scale*transformed[0]); + if (r_u1 < r_refdef.fvrectx_adj) + r_u1 = r_refdef.fvrectx_adj; + if (r_u1 > r_refdef.fvrectright_adj) + r_u1 = r_refdef.fvrectright_adj; + + scale = yscale * r_lzi1; + r_v1 = (ycenter - scale*transformed[1]); + if (r_v1 < r_refdef.fvrecty_adj) + r_v1 = r_refdef.fvrecty_adj; + if (r_v1 > r_refdef.fvrectbottom_adj) + r_v1 = r_refdef.fvrectbottom_adj; + + if (r_lzi1 > lzi0) + lzi0 = r_lzi1; + + if (lzi0 > r_nearzi) // for mipmap finding + r_nearzi = lzi0; + +// for right edges, all we want is the effect on 1/z + if (r_nearzionly) + return; + + r_emitted = 1; + + r_ceilv1 = (int) ceil(r_v1); + + +// create the edge + if (ceilv0 == r_ceilv1) + { + // we cache unclipped horizontal edges as fully clipped + if (cacheoffset != 0x7FFFFFFF) + { + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + } + + return; // horizontal edge + } + + side = ceilv0 > r_ceilv1; + + edge = edge_p++; + + edge->owner = r_pedge; + + edge->nearzi = lzi0; + + if (side == 0) + { + // trailing edge (go from p1 to p2) + v = ceilv0; + v2 = r_ceilv1 - 1; + + edge->surfs[0] = surface_p - surfaces; + edge->surfs[1] = 0; + + u_step = ((r_u1 - u0) / (r_v1 - v0)); + u = u0 + ((float)v - v0) * u_step; + } + else + { + // leading edge (go from p2 to p1) + v2 = ceilv0 - 1; + v = r_ceilv1; + + edge->surfs[0] = 0; + edge->surfs[1] = surface_p - surfaces; + + u_step = ((u0 - r_u1) / (v0 - r_v1)); + u = r_u1 + ((float)v - r_v1) * u_step; + } + + edge->u_step = u_step*0x100000; + edge->u = u*0x100000 + 0xFFFFF; + +// we need to do this to avoid stepping off the edges if a very nearly +// horizontal edge is less than epsilon above a scan, and numeric error causes +// it to incorrectly extend to the scan, and the extension of the line goes off +// the edge of the screen +// FIXME: is this actually needed? + if (edge->u < r_refdef.vrect_x_adj_shift20) + edge->u = r_refdef.vrect_x_adj_shift20; + if (edge->u > r_refdef.vrectright_adj_shift20) + edge->u = r_refdef.vrectright_adj_shift20; + +// +// sort the edge in normally +// + u_check = edge->u; + if (edge->surfs[0]) + u_check++; // sort trailers after leaders + + if (!newedges[v] || newedges[v]->u >= u_check) + { + edge->next = newedges[v]; + newedges[v] = edge; + } + else + { + pcheck = newedges[v]; + while (pcheck->next && pcheck->next->u < u_check) + pcheck = pcheck->next; + edge->next = pcheck->next; + pcheck->next = edge; + } + + edge->nextremove = removeedges[v2]; + removeedges[v2] = edge; +} + + +/* +================ +R_ClipEdge +================ +*/ +void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) +{ + float d0, d1, f; + mvertex_t clipvert; + + if (clip) + { + do + { + d0 = DotProduct (pv0->position, clip->normal) - clip->dist; + d1 = DotProduct (pv1->position, clip->normal) - clip->dist; + + if (d0 >= 0) + { + // point 0 is unclipped + if (d1 >= 0) + { + // both points are unclipped + continue; + } + + // only point 1 is clipped + + // we don't cache clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftexit = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightexit = clipvert; + } + + R_ClipEdge (pv0, &clipvert, clip->next); + return; + } + else + { + // point 0 is clipped + if (d1 < 0) + { + // both points are clipped + // we do cache fully clipped edges + if (!r_leftclipped) + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + return; + } + + // only point 0 is clipped + r_lastvertvalid = false; + + // we don't cache partially clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftenter = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightenter = clipvert; + } + + R_ClipEdge (&clipvert, pv1, clip->next); + return; + } + } while ((clip = clip->next) != NULL); + } + +// add the edge + R_EmitEdge (pv0, pv1); +} + +#endif // !id386 + + +/* +================ +R_EmitCachedEdge +================ +*/ +void R_EmitCachedEdge (void) +{ + edge_t *pedge_t; + + pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset); + + if (!pedge_t->surfs[0]) + pedge_t->surfs[0] = surface_p - surfaces; + else + pedge_t->surfs[1] = surface_p - surfaces; + + if (pedge_t->nearzi > r_nearzi) // for mipmap finding + r_nearzi = pedge_t->nearzi; + + r_emitted = 1; +} + + +/* +================ +R_RenderFace +================ +*/ +void R_RenderFace (msurface_t *fa, int clipflags) +{ + int i, lindex; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t *pedges, tedge; + clipplane_t *pclip; + +// skip out if no more surfs + if ((surface_p) >= surf_max) + { + r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + fa->numedges + 4) >= edge_max) + { + r_outofedges += fa->numedges; + return; + } + + c_faceclip++; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; + pedges = currententity->model->edges; + r_lastvertvalid = false; + + for (i=0 ; inumedges ; i++) + { + lindex = currententity->model->surfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + + // if the edge is cached, we can just reuse the edge + if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], + &r_pcurrentvertbase[r_pedge->v[1]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + else + { + lindex = -lindex; + r_pedge = &pedges[lindex]; + // if the edge is cached, we can just reuse the edge + if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + // it's cached if the cached edge is valid and is owned + // by this medge_t + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], + &r_pcurrentvertbase[r_pedge->v[0]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->data = (void *)fa; + surface_p->nearzi = r_nearzi; + surface_p->flags = fa->flags; + surface_p->insubmodel = insubmodel; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentkey++; + surface_p->spans = NULL; + + pplane = fa->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + +//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); + surface_p++; +} + + +/* +================ +R_RenderBmodelFace +================ +*/ +void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) +{ + int i; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t tedge; + clipplane_t *pclip; + +// skip out if no more surfs + if (surface_p >= surf_max) + { + r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + psurf->numedges + 4) >= edge_max) + { + r_outofedges += psurf->numedges; + return; + } + + c_faceclip++; + +// this is a dummy to give the caching mechanism someplace to write to + r_pedge = &tedge; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (r_clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; +// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching +// can be used? + r_lastvertvalid = false; + + for ( ; pedges ; pedges = pedges->pnext) + { + r_leftclipped = r_rightclipped = false; + R_ClipEdge (pedges->v[0], pedges->v[1], pclip); + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->data = (void *)psurf; + surface_p->nearzi = r_nearzi; + surface_p->flags = psurf->flags; + surface_p->insubmodel = true; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentbkey; + surface_p->spans = NULL; + + pplane = psurf->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + +//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); + surface_p++; +} + + +/* +================ +R_RenderPoly +================ +*/ +void R_RenderPoly (msurface_t *fa, int clipflags) +{ + int i, lindex, lnumverts, s_axis, t_axis; + float dist, lastdist, lzi, scale, u, v, frac; + unsigned mask; + vec3_t local, transformed; + clipplane_t *pclip; + medge_t *pedges; + mplane_t *pplane; + mvertex_t verts[2][100]; //FIXME: do real number + polyvert_t pverts[100]; //FIXME: do real number, safely + int vertpage, newverts, newpage, lastvert; + qboolean visible; + +// FIXME: clean this up and make it faster +// FIXME: guard against running out of vertices + + s_axis = t_axis = 0; // keep compiler happy + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// reconstruct the polygon +// FIXME: these should be precalculated and loaded off disk + pedges = currententity->model->edges; + lnumverts = fa->numedges; + vertpage = 0; + + for (i=0 ; imodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]]; + } + else + { + r_pedge = &pedges[-lindex]; + verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]]; + } + } + +// clip the polygon, done if not visible + while (pclip) + { + lastvert = lnumverts - 1; + lastdist = DotProduct (verts[vertpage][lastvert].position, + pclip->normal) - pclip->dist; + + visible = false; + newverts = 0; + newpage = vertpage ^ 1; + + for (i=0 ; inormal) - + pclip->dist; + + if ((lastdist > 0) != (dist > 0)) + { + frac = dist / (dist - lastdist); + verts[newpage][newverts].position[0] = + verts[vertpage][i].position[0] + + ((verts[vertpage][lastvert].position[0] - + verts[vertpage][i].position[0]) * frac); + verts[newpage][newverts].position[1] = + verts[vertpage][i].position[1] + + ((verts[vertpage][lastvert].position[1] - + verts[vertpage][i].position[1]) * frac); + verts[newpage][newverts].position[2] = + verts[vertpage][i].position[2] + + ((verts[vertpage][lastvert].position[2] - + verts[vertpage][i].position[2]) * frac); + newverts++; + } + + if (dist >= 0) + { + verts[newpage][newverts] = verts[vertpage][i]; + newverts++; + visible = true; + } + + lastvert = i; + lastdist = dist; + } + + if (!visible || (newverts < 3)) + return; + + lnumverts = newverts; + vertpage ^= 1; + pclip = pclip->next; + } + +// transform and project, remembering the z values at the vertices and +// r_nearzi, and extract the s and t coordinates at the vertices + pplane = fa->plane; + switch (pplane->type) + { + case PLANE_X: + case PLANE_ANYX: + s_axis = 1; + t_axis = 2; + break; + case PLANE_Y: + case PLANE_ANYY: + s_axis = 0; + t_axis = 2; + break; + case PLANE_Z: + case PLANE_ANYZ: + s_axis = 0; + t_axis = 1; + break; + } + + r_nearzi = 0; + + for (i=0 ; i r_nearzi) // for mipmap finding + r_nearzi = lzi; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi; + u = (xcenter + scale*transformed[0]); + if (u < r_refdef.fvrectx_adj) + u = r_refdef.fvrectx_adj; + if (u > r_refdef.fvrectright_adj) + u = r_refdef.fvrectright_adj; + + scale = yscale * lzi; + v = (ycenter - scale*transformed[1]); + if (v < r_refdef.fvrecty_adj) + v = r_refdef.fvrecty_adj; + if (v > r_refdef.fvrectbottom_adj) + v = r_refdef.fvrectbottom_adj; + + pverts[i].u = u; + pverts[i].v = v; + pverts[i].zi = lzi; + pverts[i].s = verts[vertpage][i].position[s_axis]; + pverts[i].t = verts[vertpage][i].position[t_axis]; + } + +// build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z +// for each vertex + r_polydesc.numverts = lnumverts; + r_polydesc.nearzi = r_nearzi; + r_polydesc.pcurrentface = fa; + r_polydesc.pverts = pverts; + +// draw the polygon + D_DrawPoly (); +} + + +/* +================ +R_ZDrawSubmodelPolys +================ +*/ +void R_ZDrawSubmodelPolys (model_t *pmodel) +{ + int i, numsurfaces; + msurface_t *psurf; + float dot; + mplane_t *pplane; + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + // FIXME: use bounding-box-based frustum clipping info? + R_RenderPoly (psurf, 15); + } + } +} + diff --git a/WinQuake/r_drawa.s b/WinQuake/r_drawa.s index 3cb2239..60874e8 100644 --- a/WinQuake/r_drawa.s +++ b/WinQuake/r_drawa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // r_drawa.s // x86 assembly-language edge clipping and emission code diff --git a/WinQuake/r_edge.c b/WinQuake/r_edge.c index d434799..12a201d 100644 --- a/WinQuake/r_edge.c +++ b/WinQuake/r_edge.c @@ -1,774 +1,774 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_edge.c - -#include "quakedef.h" -#include "r_local.h" - -#if 0 -// FIXME -the complex cases add new polys on most lines, so dont optimize for keeping them the same -have multiple free span lists to try to get better coherence? -low depth complexity -- 1 to 3 or so - -this breaks spans at every edge, even hidden ones (bad) - -have a sentinal at both ends? -#endif - - -edge_t *auxedges; -edge_t *r_edges, *edge_p, *edge_max; - -surf_t *surfaces, *surface_p, *surf_max; - -// surfaces are generated in back to front order by the bsp, so if a surf -// pointer is greater than another one, it should be drawn in front -// surfaces[1] is the background, and is used as the active surface stack - -edge_t *newedges[MAXHEIGHT]; -edge_t *removeedges[MAXHEIGHT]; - -espan_t *span_p, *max_span_p; - -int r_currentkey; - -extern int screenwidth; - -int current_iv; - -int edge_head_u_shift20, edge_tail_u_shift20; - -static void (*pdrawfunc)(void); - -edge_t edge_head; -edge_t edge_tail; -edge_t edge_aftertail; -edge_t edge_sentinel; - -float fv; - -void R_GenerateSpans (void); -void R_GenerateSpansBackward (void); - -void R_LeadingEdge (edge_t *edge); -void R_LeadingEdgeBackwards (edge_t *edge); -void R_TrailingEdge (surf_t *surf, edge_t *edge); - - -//============================================================================= - - -/* -============== -R_DrawCulledPolys -============== -*/ -void R_DrawCulledPolys (void) -{ - surf_t *s; - msurface_t *pface; - - currententity = &cl_entities[0]; - - if (r_worldpolysbacktofront) - { - for (s=surface_p-1 ; s>&surfaces[1] ; s--) - { - if (!s->spans) - continue; - - if (!(s->flags & SURF_DRAWBACKGROUND)) - { - pface = (msurface_t *)s->data; - R_RenderPoly (pface, 15); - } - } - } - else - { - for (s = &surfaces[1] ; sspans) - continue; - - if (!(s->flags & SURF_DRAWBACKGROUND)) - { - pface = (msurface_t *)s->data; - R_RenderPoly (pface, 15); - } - } - } -} - - -/* -============== -R_BeginEdgeFrame -============== -*/ -void R_BeginEdgeFrame (void) -{ - int v; - - edge_p = r_edges; - edge_max = &r_edges[r_numallocatededges]; - - surface_p = &surfaces[2]; // background is surface 1, - // surface 0 is a dummy - surfaces[1].spans = NULL; // no background spans yet - surfaces[1].flags = SURF_DRAWBACKGROUND; - -// put the background behind everything in the world - if (r_draworder.value) - { - pdrawfunc = R_GenerateSpansBackward; - surfaces[1].key = 0; - r_currentkey = 1; - } - else - { - pdrawfunc = R_GenerateSpans; - surfaces[1].key = 0x7FFFFFFF; - r_currentkey = 0; - } - -// FIXME: set with memset - for (v=r_refdef.vrect.y ; vnext; -edgesearch: - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist=edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist=edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist=edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist=edgelist->next; - goto edgesearch; - - // insert edgestoadd before edgelist -addedge: - edgestoadd->next = edgelist; - edgestoadd->prev = edgelist->prev; - edgelist->prev->next = edgestoadd; - edgelist->prev = edgestoadd; - } while ((edgestoadd = next_edge) != NULL); -} - -#endif // !id386 - - -#if !id386 - -/* -============== -R_RemoveEdges -============== -*/ -void R_RemoveEdges (edge_t *pedge) -{ - - do - { - pedge->next->prev = pedge->prev; - pedge->prev->next = pedge->next; - } while ((pedge = pedge->nextremove) != NULL); -} - -#endif // !id386 - - -#if !id386 - -/* -============== -R_StepActiveU -============== -*/ -void R_StepActiveU (edge_t *pedge) -{ - edge_t *pnext_edge, *pwedge; - - while (1) - { -nextedge: - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - goto nextedge; - -pushback: - if (pedge == &edge_aftertail) - return; - - // push it back to keep it sorted - pnext_edge = pedge->next; - - // pull the edge out of the edge list - pedge->next->prev = pedge->prev; - pedge->prev->next = pedge->next; - - // find out where the edge goes in the edge list - pwedge = pedge->prev->prev; - - while (pwedge->u > pedge->u) - { - pwedge = pwedge->prev; - } - - // put the edge back into the edge list - pedge->next = pwedge->next; - pedge->prev = pwedge; - pedge->next->prev = pedge; - pwedge->next = pedge; - - pedge = pnext_edge; - if (pedge == &edge_tail) - return; - } -} - -#endif // !id386 - - -/* -============== -R_CleanupSpan -============== -*/ -void R_CleanupSpan () -{ - surf_t *surf; - int iu; - espan_t *span; - -// now that we've reached the right edge of the screen, we're done with any -// unfinished surfaces, so emit a span for whatever's on top - surf = surfaces[1].next; - iu = edge_tail_u_shift20; - if (iu > surf->last_u) - { - span = span_p++; - span->u = surf->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf->spans; - surf->spans = span; - } - -// reset spanstate for all surfaces in the surface stack - do - { - surf->spanstate = 0; - surf = surf->next; - } while (surf != &surfaces[1]); -} - - -/* -============== -R_LeadingEdgeBackwards -============== -*/ -void R_LeadingEdgeBackwards (edge_t *edge) -{ - espan_t *span; - surf_t *surf, *surf2; - int iu; - -// it's adding a new surface in, so find the correct place - surf = &surfaces[edge->surfs[1]]; - -// don't start a span if this is an inverted span, with the end -// edge preceding the start edge (that is, we've already seen the -// end edge) - if (++surf->spanstate == 1) - { - surf2 = surfaces[1].next; - - if (surf->key > surf2->key) - goto newtop; - - // if it's two surfaces on the same plane, the one that's already - // active is in front, so keep going unless it's a bmodel - if (surf->insubmodel && (surf->key == surf2->key)) - { - // must be two bmodels in the same leaf; don't care, because they'll - // never be farthest anyway - goto newtop; - } - -continue_search: - - do - { - surf2 = surf2->next; - } while (surf->key < surf2->key); - - if (surf->key == surf2->key) - { - // if it's two surfaces on the same plane, the one that's already - // active is in front, so keep going unless it's a bmodel - if (!surf->insubmodel) - goto continue_search; - - // must be two bmodels in the same leaf; don't care which is really - // in front, because they'll never be farthest anyway - } - - goto gotposition; - -newtop: - // emit a span (obscures current top) - iu = edge->u >> 20; - - if (iu > surf2->last_u) - { - span = span_p++; - span->u = surf2->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf2->spans; - surf2->spans = span; - } - - // set last_u on the new span - surf->last_u = iu; - -gotposition: - // insert before surf2 - surf->next = surf2; - surf->prev = surf2->prev; - surf2->prev->next = surf; - surf2->prev = surf; - } -} - - -/* -============== -R_TrailingEdge -============== -*/ -void R_TrailingEdge (surf_t *surf, edge_t *edge) -{ - espan_t *span; - int iu; - -// don't generate a span if this is an inverted span, with the end -// edge preceding the start edge (that is, we haven't seen the -// start edge yet) - if (--surf->spanstate == 0) - { - if (surf->insubmodel) - r_bmodelactive--; - - if (surf == surfaces[1].next) - { - // emit a span (current top going away) - iu = edge->u >> 20; - if (iu > surf->last_u) - { - span = span_p++; - span->u = surf->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf->spans; - surf->spans = span; - } - - // set last_u on the surface below - surf->next->last_u = iu; - } - - surf->prev->next = surf->next; - surf->next->prev = surf->prev; - } -} - - -#if !id386 - -/* -============== -R_LeadingEdge -============== -*/ -void R_LeadingEdge (edge_t *edge) -{ - espan_t *span; - surf_t *surf, *surf2; - int iu; - double fu, newzi, testzi, newzitop, newzibottom; - - if (edge->surfs[1]) - { - // it's adding a new surface in, so find the correct place - surf = &surfaces[edge->surfs[1]]; - - // don't start a span if this is an inverted span, with the end - // edge preceding the start edge (that is, we've already seen the - // end edge) - if (++surf->spanstate == 1) - { - if (surf->insubmodel) - r_bmodelactive++; - - surf2 = surfaces[1].next; - - if (surf->key < surf2->key) - goto newtop; - - // if it's two surfaces on the same plane, the one that's already - // active is in front, so keep going unless it's a bmodel - if (surf->insubmodel && (surf->key == surf2->key)) - { - // must be two bmodels in the same leaf; sort on 1/z - fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); - newzi = surf->d_ziorigin + fv*surf->d_zistepv + - fu*surf->d_zistepu; - newzibottom = newzi * 0.99; - - testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + - fu*surf2->d_zistepu; - - if (newzibottom >= testzi) - { - goto newtop; - } - - newzitop = newzi * 1.01; - if (newzitop >= testzi) - { - if (surf->d_zistepu >= surf2->d_zistepu) - { - goto newtop; - } - } - } - -continue_search: - - do - { - surf2 = surf2->next; - } while (surf->key > surf2->key); - - if (surf->key == surf2->key) - { - // if it's two surfaces on the same plane, the one that's already - // active is in front, so keep going unless it's a bmodel - if (!surf->insubmodel) - goto continue_search; - - // must be two bmodels in the same leaf; sort on 1/z - fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); - newzi = surf->d_ziorigin + fv*surf->d_zistepv + - fu*surf->d_zistepu; - newzibottom = newzi * 0.99; - - testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + - fu*surf2->d_zistepu; - - if (newzibottom >= testzi) - { - goto gotposition; - } - - newzitop = newzi * 1.01; - if (newzitop >= testzi) - { - if (surf->d_zistepu >= surf2->d_zistepu) - { - goto gotposition; - } - } - - goto continue_search; - } - - goto gotposition; - -newtop: - // emit a span (obscures current top) - iu = edge->u >> 20; - - if (iu > surf2->last_u) - { - span = span_p++; - span->u = surf2->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf2->spans; - surf2->spans = span; - } - - // set last_u on the new span - surf->last_u = iu; - -gotposition: - // insert before surf2 - surf->next = surf2; - surf->prev = surf2->prev; - surf2->prev->next = surf; - surf2->prev = surf; - } - } -} - - -/* -============== -R_GenerateSpans -============== -*/ -void R_GenerateSpans (void) -{ - edge_t *edge; - surf_t *surf; - - r_bmodelactive = 0; - -// clear active surfaces to just the background surface - surfaces[1].next = surfaces[1].prev = &surfaces[1]; - surfaces[1].last_u = edge_head_u_shift20; - -// generate spans - for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) - { - if (edge->surfs[0]) - { - // it has a left surface, so a surface is going away for this span - surf = &surfaces[edge->surfs[0]]; - - R_TrailingEdge (surf, edge); - - if (!edge->surfs[1]) - continue; - } - - R_LeadingEdge (edge); - } - - R_CleanupSpan (); -} - -#endif // !id386 - - -/* -============== -R_GenerateSpansBackward -============== -*/ -void R_GenerateSpansBackward (void) -{ - edge_t *edge; - - r_bmodelactive = 0; - -// clear active surfaces to just the background surface - surfaces[1].next = surfaces[1].prev = &surfaces[1]; - surfaces[1].last_u = edge_head_u_shift20; - -// generate spans - for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) - { - if (edge->surfs[0]) - R_TrailingEdge (&surfaces[edge->surfs[0]], edge); - - if (edge->surfs[1]) - R_LeadingEdgeBackwards (edge); - } - - R_CleanupSpan (); -} - - -/* -============== -R_ScanEdges - -Input: -newedges[] array - this has links to edges, which have links to surfaces - -Output: -Each surface has a linked list of its visible spans -============== -*/ -void R_ScanEdges (void) -{ - int iv, bottom; - byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE]; - espan_t *basespan_p; - surf_t *s; - - basespan_p = (espan_t *) - ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; - - span_p = basespan_p; - -// clear active edges to just the background edges around the whole screen -// FIXME: most of this only needs to be set up once - edge_head.u = r_refdef.vrect.x << 20; - edge_head_u_shift20 = edge_head.u >> 20; - edge_head.u_step = 0; - edge_head.prev = NULL; - edge_head.next = &edge_tail; - edge_head.surfs[0] = 0; - edge_head.surfs[1] = 1; - - edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; - edge_tail_u_shift20 = edge_tail.u >> 20; - edge_tail.u_step = 0; - edge_tail.prev = &edge_head; - edge_tail.next = &edge_aftertail; - edge_tail.surfs[0] = 1; - edge_tail.surfs[1] = 0; - - edge_aftertail.u = -1; // force a move - edge_aftertail.u_step = 0; - edge_aftertail.next = &edge_sentinel; - edge_aftertail.prev = &edge_tail; - -// FIXME: do we need this now that we clamp x in r_draw.c? - edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this - edge_sentinel.prev = &edge_aftertail; - -// -// process all scan lines -// - bottom = r_refdef.vrectbottom - 1; - - for (iv=r_refdef.vrect.y ; iv= max_span_p) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - - if (r_drawculledpolys) - { - R_DrawCulledPolys (); - } - else - { - D_DrawSurfaces (); - } - - // clear the surface span pointers - for (s = &surfaces[1] ; sspans = NULL; - - span_p = basespan_p; - } - - if (removeedges[iv]) - R_RemoveEdges (removeedges[iv]); - - if (edge_head.next != &edge_tail) - R_StepActiveU (edge_head.next); - } - -// do the last scan (no need to step or sort or remove on the last scan) - - current_iv = iv; - fv = (float)iv; - -// mark that the head (background start) span is pre-included - surfaces[1].spanstate = 1; - - if (newedges[iv]) - R_InsertNewEdges (newedges[iv], edge_head.next); - - (*pdrawfunc) (); - -// draw whatever's left in the span list - if (r_drawculledpolys) - R_DrawCulledPolys (); - else - D_DrawSurfaces (); -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_edge.c + +#include "quakedef.h" +#include "r_local.h" + +#if 0 +// FIXME +the complex cases add new polys on most lines, so dont optimize for keeping them the same +have multiple free span lists to try to get better coherence? +low depth complexity -- 1 to 3 or so + +this breaks spans at every edge, even hidden ones (bad) + +have a sentinal at both ends? +#endif + + +edge_t *auxedges; +edge_t *r_edges, *edge_p, *edge_max; + +surf_t *surfaces, *surface_p, *surf_max; + +// surfaces are generated in back to front order by the bsp, so if a surf +// pointer is greater than another one, it should be drawn in front +// surfaces[1] is the background, and is used as the active surface stack + +edge_t *newedges[MAXHEIGHT]; +edge_t *removeedges[MAXHEIGHT]; + +espan_t *span_p, *max_span_p; + +int r_currentkey; + +extern int screenwidth; + +int current_iv; + +int edge_head_u_shift20, edge_tail_u_shift20; + +static void (*pdrawfunc)(void); + +edge_t edge_head; +edge_t edge_tail; +edge_t edge_aftertail; +edge_t edge_sentinel; + +float fv; + +void R_GenerateSpans (void); +void R_GenerateSpansBackward (void); + +void R_LeadingEdge (edge_t *edge); +void R_LeadingEdgeBackwards (edge_t *edge); +void R_TrailingEdge (surf_t *surf, edge_t *edge); + + +//============================================================================= + + +/* +============== +R_DrawCulledPolys +============== +*/ +void R_DrawCulledPolys (void) +{ + surf_t *s; + msurface_t *pface; + + currententity = &cl_entities[0]; + + if (r_worldpolysbacktofront) + { + for (s=surface_p-1 ; s>&surfaces[1] ; s--) + { + if (!s->spans) + continue; + + if (!(s->flags & SURF_DRAWBACKGROUND)) + { + pface = (msurface_t *)s->data; + R_RenderPoly (pface, 15); + } + } + } + else + { + for (s = &surfaces[1] ; sspans) + continue; + + if (!(s->flags & SURF_DRAWBACKGROUND)) + { + pface = (msurface_t *)s->data; + R_RenderPoly (pface, 15); + } + } + } +} + + +/* +============== +R_BeginEdgeFrame +============== +*/ +void R_BeginEdgeFrame (void) +{ + int v; + + edge_p = r_edges; + edge_max = &r_edges[r_numallocatededges]; + + surface_p = &surfaces[2]; // background is surface 1, + // surface 0 is a dummy + surfaces[1].spans = NULL; // no background spans yet + surfaces[1].flags = SURF_DRAWBACKGROUND; + +// put the background behind everything in the world + if (r_draworder.value) + { + pdrawfunc = R_GenerateSpansBackward; + surfaces[1].key = 0; + r_currentkey = 1; + } + else + { + pdrawfunc = R_GenerateSpans; + surfaces[1].key = 0x7FFFFFFF; + r_currentkey = 0; + } + +// FIXME: set with memset + for (v=r_refdef.vrect.y ; vnext; +edgesearch: + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + goto edgesearch; + + // insert edgestoadd before edgelist +addedge: + edgestoadd->next = edgelist; + edgestoadd->prev = edgelist->prev; + edgelist->prev->next = edgestoadd; + edgelist->prev = edgestoadd; + } while ((edgestoadd = next_edge) != NULL); +} + +#endif // !id386 + + +#if !id386 + +/* +============== +R_RemoveEdges +============== +*/ +void R_RemoveEdges (edge_t *pedge) +{ + + do + { + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + } while ((pedge = pedge->nextremove) != NULL); +} + +#endif // !id386 + + +#if !id386 + +/* +============== +R_StepActiveU +============== +*/ +void R_StepActiveU (edge_t *pedge) +{ + edge_t *pnext_edge, *pwedge; + + while (1) + { +nextedge: + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + goto nextedge; + +pushback: + if (pedge == &edge_aftertail) + return; + + // push it back to keep it sorted + pnext_edge = pedge->next; + + // pull the edge out of the edge list + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + + // find out where the edge goes in the edge list + pwedge = pedge->prev->prev; + + while (pwedge->u > pedge->u) + { + pwedge = pwedge->prev; + } + + // put the edge back into the edge list + pedge->next = pwedge->next; + pedge->prev = pwedge; + pedge->next->prev = pedge; + pwedge->next = pedge; + + pedge = pnext_edge; + if (pedge == &edge_tail) + return; + } +} + +#endif // !id386 + + +/* +============== +R_CleanupSpan +============== +*/ +void R_CleanupSpan () +{ + surf_t *surf; + int iu; + espan_t *span; + +// now that we've reached the right edge of the screen, we're done with any +// unfinished surfaces, so emit a span for whatever's on top + surf = surfaces[1].next; + iu = edge_tail_u_shift20; + if (iu > surf->last_u) + { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + +// reset spanstate for all surfaces in the surface stack + do + { + surf->spanstate = 0; + surf = surf->next; + } while (surf != &surfaces[1]); +} + + +/* +============== +R_LeadingEdgeBackwards +============== +*/ +void R_LeadingEdgeBackwards (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + +// it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + +// don't start a span if this is an inverted span, with the end +// edge preceding the start edge (that is, we've already seen the +// end edge) + if (++surf->spanstate == 1) + { + surf2 = surfaces[1].next; + + if (surf->key > surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) + { + // must be two bmodels in the same leaf; don't care, because they'll + // never be farthest anyway + goto newtop; + } + +continue_search: + + do + { + surf2 = surf2->next; + } while (surf->key < surf2->key); + + if (surf->key == surf2->key) + { + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; don't care which is really + // in front, because they'll never be farthest anyway + } + + goto gotposition; + +newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) + { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + + // set last_u on the new span + surf->last_u = iu; + +gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } +} + + +/* +============== +R_TrailingEdge +============== +*/ +void R_TrailingEdge (surf_t *surf, edge_t *edge) +{ + espan_t *span; + int iu; + +// don't generate a span if this is an inverted span, with the end +// edge preceding the start edge (that is, we haven't seen the +// start edge yet) + if (--surf->spanstate == 0) + { + if (surf->insubmodel) + r_bmodelactive--; + + if (surf == surfaces[1].next) + { + // emit a span (current top going away) + iu = edge->u >> 20; + if (iu > surf->last_u) + { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + + // set last_u on the surface below + surf->next->last_u = iu; + } + + surf->prev->next = surf->next; + surf->next->prev = surf->prev; + } +} + + +#if !id386 + +/* +============== +R_LeadingEdge +============== +*/ +void R_LeadingEdge (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + double fu, newzi, testzi, newzitop, newzibottom; + + if (edge->surfs[1]) + { + // it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + + // don't start a span if this is an inverted span, with the end + // edge preceding the start edge (that is, we've already seen the + // end edge) + if (++surf->spanstate == 1) + { + if (surf->insubmodel) + r_bmodelactive++; + + surf2 = surfaces[1].next; + + if (surf->key < surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) + { + // must be two bmodels in the same leaf; sort on 1/z + fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv*surf->d_zistepv + + fu*surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + + fu*surf2->d_zistepu; + + if (newzibottom >= testzi) + { + goto newtop; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) + { + if (surf->d_zistepu >= surf2->d_zistepu) + { + goto newtop; + } + } + } + +continue_search: + + do + { + surf2 = surf2->next; + } while (surf->key > surf2->key); + + if (surf->key == surf2->key) + { + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; sort on 1/z + fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv*surf->d_zistepv + + fu*surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + + fu*surf2->d_zistepu; + + if (newzibottom >= testzi) + { + goto gotposition; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) + { + if (surf->d_zistepu >= surf2->d_zistepu) + { + goto gotposition; + } + } + + goto continue_search; + } + + goto gotposition; + +newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) + { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + + // set last_u on the new span + surf->last_u = iu; + +gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } + } +} + + +/* +============== +R_GenerateSpans +============== +*/ +void R_GenerateSpans (void) +{ + edge_t *edge; + surf_t *surf; + + r_bmodelactive = 0; + +// clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + +// generate spans + for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) + { + if (edge->surfs[0]) + { + // it has a left surface, so a surface is going away for this span + surf = &surfaces[edge->surfs[0]]; + + R_TrailingEdge (surf, edge); + + if (!edge->surfs[1]) + continue; + } + + R_LeadingEdge (edge); + } + + R_CleanupSpan (); +} + +#endif // !id386 + + +/* +============== +R_GenerateSpansBackward +============== +*/ +void R_GenerateSpansBackward (void) +{ + edge_t *edge; + + r_bmodelactive = 0; + +// clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + +// generate spans + for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) + { + if (edge->surfs[0]) + R_TrailingEdge (&surfaces[edge->surfs[0]], edge); + + if (edge->surfs[1]) + R_LeadingEdgeBackwards (edge); + } + + R_CleanupSpan (); +} + + +/* +============== +R_ScanEdges + +Input: +newedges[] array + this has links to edges, which have links to surfaces + +Output: +Each surface has a linked list of its visible spans +============== +*/ +void R_ScanEdges (void) +{ + int iv, bottom; + byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE]; + espan_t *basespan_p; + surf_t *s; + + basespan_p = (espan_t *) + ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; + + span_p = basespan_p; + +// clear active edges to just the background edges around the whole screen +// FIXME: most of this only needs to be set up once + edge_head.u = r_refdef.vrect.x << 20; + edge_head_u_shift20 = edge_head.u >> 20; + edge_head.u_step = 0; + edge_head.prev = NULL; + edge_head.next = &edge_tail; + edge_head.surfs[0] = 0; + edge_head.surfs[1] = 1; + + edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; + edge_tail_u_shift20 = edge_tail.u >> 20; + edge_tail.u_step = 0; + edge_tail.prev = &edge_head; + edge_tail.next = &edge_aftertail; + edge_tail.surfs[0] = 1; + edge_tail.surfs[1] = 0; + + edge_aftertail.u = -1; // force a move + edge_aftertail.u_step = 0; + edge_aftertail.next = &edge_sentinel; + edge_aftertail.prev = &edge_tail; + +// FIXME: do we need this now that we clamp x in r_draw.c? + edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this + edge_sentinel.prev = &edge_aftertail; + +// +// process all scan lines +// + bottom = r_refdef.vrectbottom - 1; + + for (iv=r_refdef.vrect.y ; iv= max_span_p) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + + if (r_drawculledpolys) + { + R_DrawCulledPolys (); + } + else + { + D_DrawSurfaces (); + } + + // clear the surface span pointers + for (s = &surfaces[1] ; sspans = NULL; + + span_p = basespan_p; + } + + if (removeedges[iv]) + R_RemoveEdges (removeedges[iv]); + + if (edge_head.next != &edge_tail) + R_StepActiveU (edge_head.next); + } + +// do the last scan (no need to step or sort or remove on the last scan) + + current_iv = iv; + fv = (float)iv; + +// mark that the head (background start) span is pre-included + surfaces[1].spanstate = 1; + + if (newedges[iv]) + R_InsertNewEdges (newedges[iv], edge_head.next); + + (*pdrawfunc) (); + +// draw whatever's left in the span list + if (r_drawculledpolys) + R_DrawCulledPolys (); + else + D_DrawSurfaces (); +} + + diff --git a/WinQuake/r_edgea.s b/WinQuake/r_edgea.s index f67130f..8507a5b 100644 --- a/WinQuake/r_edgea.s +++ b/WinQuake/r_edgea.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // r_edgea.s // x86 assembly-language edge-processing code. diff --git a/WinQuake/r_efrag.c b/WinQuake/r_efrag.c index 5e4d3f9..f502d86 100644 --- a/WinQuake/r_efrag.c +++ b/WinQuake/r_efrag.c @@ -1,276 +1,276 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_efrag.c - -#include "quakedef.h" -#include "r_local.h" - -mnode_t *r_pefragtopnode; - - -//=========================================================================== - -/* -=============================================================================== - - ENTITY FRAGMENT FUNCTIONS - -=============================================================================== -*/ - -efrag_t **lastlink; - -vec3_t r_emins, r_emaxs; - -entity_t *r_addent; - - -/* -================ -R_RemoveEfrags - -Call when removing an object from the world or moving it to another position -================ -*/ -void R_RemoveEfrags (entity_t *ent) -{ - efrag_t *ef, *old, *walk, **prev; - - ef = ent->efrag; - - while (ef) - { - prev = &ef->leaf->efrags; - while (1) - { - walk = *prev; - if (!walk) - break; - if (walk == ef) - { // remove this fragment - *prev = ef->leafnext; - break; - } - else - prev = &walk->leafnext; - } - - old = ef; - ef = ef->entnext; - - // put it on the free list - old->entnext = cl.free_efrags; - cl.free_efrags = old; - } - - ent->efrag = NULL; -} - -/* -=================== -R_SplitEntityOnNode -=================== -*/ -void R_SplitEntityOnNode (mnode_t *node) -{ - efrag_t *ef; - mplane_t *splitplane; - mleaf_t *leaf; - int sides; - - if (node->contents == CONTENTS_SOLID) - { - return; - } - -// add an efrag if the node is a leaf - - if ( node->contents < 0) - { - if (!r_pefragtopnode) - r_pefragtopnode = node; - - leaf = (mleaf_t *)node; - -// grab an efrag off the free list - ef = cl.free_efrags; - if (!ef) - { - Con_Printf ("Too many efrags!\n"); - return; // no free fragments... - } - cl.free_efrags = cl.free_efrags->entnext; - - ef->entity = r_addent; - -// add the entity link - *lastlink = ef; - lastlink = &ef->entnext; - ef->entnext = NULL; - -// set the leaf links - ef->leaf = leaf; - ef->leafnext = leaf->efrags; - leaf->efrags = ef; - - return; - } - -// NODE_MIXED - - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); - - if (sides == 3) - { - // split on this plane - // if this is the first splitter of this bmodel, remember it - if (!r_pefragtopnode) - r_pefragtopnode = node; - } - -// recurse down the contacted sides - if (sides & 1) - R_SplitEntityOnNode (node->children[0]); - - if (sides & 2) - R_SplitEntityOnNode (node->children[1]); -} - - -/* -=================== -R_SplitEntityOnNode2 -=================== -*/ -void R_SplitEntityOnNode2 (mnode_t *node) -{ - mplane_t *splitplane; - int sides; - - if (node->visframe != r_visframecount) - return; - - if (node->contents < 0) - { - if (node->contents != CONTENTS_SOLID) - r_pefragtopnode = node; // we've reached a non-solid leaf, so it's - // visible and not BSP clipped - return; - } - - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); - - if (sides == 3) - { - // remember first splitter - r_pefragtopnode = node; - return; - } - -// not split yet; recurse down the contacted side - if (sides & 1) - R_SplitEntityOnNode2 (node->children[0]); - else - R_SplitEntityOnNode2 (node->children[1]); -} - - -/* -=========== -R_AddEfrags -=========== -*/ -void R_AddEfrags (entity_t *ent) -{ - model_t *entmodel; - int i; - - if (!ent->model) - return; - - if (ent == cl_entities) - return; // never add the world - - r_addent = ent; - - lastlink = &ent->efrag; - r_pefragtopnode = NULL; - - entmodel = ent->model; - - for (i=0 ; i<3 ; i++) - { - r_emins[i] = ent->origin[i] + entmodel->mins[i]; - r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; - } - - R_SplitEntityOnNode (cl.worldmodel->nodes); - - ent->topnode = r_pefragtopnode; -} - - -/* -================ -R_StoreEfrags - -// FIXME: a lot of this goes away with edge-based -================ -*/ -void R_StoreEfrags (efrag_t **ppefrag) -{ - entity_t *pent; - model_t *clmodel; - efrag_t *pefrag; - - - while ((pefrag = *ppefrag) != NULL) - { - pent = pefrag->entity; - clmodel = pent->model; - - switch (clmodel->type) - { - case mod_alias: - case mod_brush: - case mod_sprite: - pent = pefrag->entity; - - if ((pent->visframe != r_framecount) && - (cl_numvisedicts < MAX_VISEDICTS)) - { - cl_visedicts[cl_numvisedicts++] = pent; - - // mark that we've recorded this entity for this frame - pent->visframe = r_framecount; - } - - ppefrag = &pefrag->leafnext; - break; - - default: - Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); - } - } -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_efrag.c + +#include "quakedef.h" +#include "r_local.h" + +mnode_t *r_pefragtopnode; + + +//=========================================================================== + +/* +=============================================================================== + + ENTITY FRAGMENT FUNCTIONS + +=============================================================================== +*/ + +efrag_t **lastlink; + +vec3_t r_emins, r_emaxs; + +entity_t *r_addent; + + +/* +================ +R_RemoveEfrags + +Call when removing an object from the world or moving it to another position +================ +*/ +void R_RemoveEfrags (entity_t *ent) +{ + efrag_t *ef, *old, *walk, **prev; + + ef = ent->efrag; + + while (ef) + { + prev = &ef->leaf->efrags; + while (1) + { + walk = *prev; + if (!walk) + break; + if (walk == ef) + { // remove this fragment + *prev = ef->leafnext; + break; + } + else + prev = &walk->leafnext; + } + + old = ef; + ef = ef->entnext; + + // put it on the free list + old->entnext = cl.free_efrags; + cl.free_efrags = old; + } + + ent->efrag = NULL; +} + +/* +=================== +R_SplitEntityOnNode +=================== +*/ +void R_SplitEntityOnNode (mnode_t *node) +{ + efrag_t *ef; + mplane_t *splitplane; + mleaf_t *leaf; + int sides; + + if (node->contents == CONTENTS_SOLID) + { + return; + } + +// add an efrag if the node is a leaf + + if ( node->contents < 0) + { + if (!r_pefragtopnode) + r_pefragtopnode = node; + + leaf = (mleaf_t *)node; + +// grab an efrag off the free list + ef = cl.free_efrags; + if (!ef) + { + Con_Printf ("Too many efrags!\n"); + return; // no free fragments... + } + cl.free_efrags = cl.free_efrags->entnext; + + ef->entity = r_addent; + +// add the entity link + *lastlink = ef; + lastlink = &ef->entnext; + ef->entnext = NULL; + +// set the leaf links + ef->leaf = leaf; + ef->leafnext = leaf->efrags; + leaf->efrags = ef; + + return; + } + +// NODE_MIXED + + splitplane = node->plane; + sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); + + if (sides == 3) + { + // split on this plane + // if this is the first splitter of this bmodel, remember it + if (!r_pefragtopnode) + r_pefragtopnode = node; + } + +// recurse down the contacted sides + if (sides & 1) + R_SplitEntityOnNode (node->children[0]); + + if (sides & 2) + R_SplitEntityOnNode (node->children[1]); +} + + +/* +=================== +R_SplitEntityOnNode2 +=================== +*/ +void R_SplitEntityOnNode2 (mnode_t *node) +{ + mplane_t *splitplane; + int sides; + + if (node->visframe != r_visframecount) + return; + + if (node->contents < 0) + { + if (node->contents != CONTENTS_SOLID) + r_pefragtopnode = node; // we've reached a non-solid leaf, so it's + // visible and not BSP clipped + return; + } + + splitplane = node->plane; + sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); + + if (sides == 3) + { + // remember first splitter + r_pefragtopnode = node; + return; + } + +// not split yet; recurse down the contacted side + if (sides & 1) + R_SplitEntityOnNode2 (node->children[0]); + else + R_SplitEntityOnNode2 (node->children[1]); +} + + +/* +=========== +R_AddEfrags +=========== +*/ +void R_AddEfrags (entity_t *ent) +{ + model_t *entmodel; + int i; + + if (!ent->model) + return; + + if (ent == cl_entities) + return; // never add the world + + r_addent = ent; + + lastlink = &ent->efrag; + r_pefragtopnode = NULL; + + entmodel = ent->model; + + for (i=0 ; i<3 ; i++) + { + r_emins[i] = ent->origin[i] + entmodel->mins[i]; + r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; + } + + R_SplitEntityOnNode (cl.worldmodel->nodes); + + ent->topnode = r_pefragtopnode; +} + + +/* +================ +R_StoreEfrags + +// FIXME: a lot of this goes away with edge-based +================ +*/ +void R_StoreEfrags (efrag_t **ppefrag) +{ + entity_t *pent; + model_t *clmodel; + efrag_t *pefrag; + + + while ((pefrag = *ppefrag) != NULL) + { + pent = pefrag->entity; + clmodel = pent->model; + + switch (clmodel->type) + { + case mod_alias: + case mod_brush: + case mod_sprite: + pent = pefrag->entity; + + if ((pent->visframe != r_framecount) && + (cl_numvisedicts < MAX_VISEDICTS)) + { + cl_visedicts[cl_numvisedicts++] = pent; + + // mark that we've recorded this entity for this frame + pent->visframe = r_framecount; + } + + ppefrag = &pefrag->leafnext; + break; + + default: + Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); + } + } +} + + diff --git a/WinQuake/r_light.c b/WinQuake/r_light.c index f735d50..14350e8 100644 --- a/WinQuake/r_light.c +++ b/WinQuake/r_light.c @@ -1,260 +1,260 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_light.c - -#include "quakedef.h" -#include "r_local.h" - -int r_dlightframecount; - - -/* -================== -R_AnimateLight -================== -*/ -void R_AnimateLight (void) -{ - int i,j,k; - -// -// light animations -// 'm' is normal light, 'a' is no light, 'z' is double bright - i = (int)(cl.time*10); - for (j=0 ; jcontents < 0) - return; - - splitplane = node->plane; - dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; - - if (dist > light->radius) - { - R_MarkLights (light, bit, node->children[0]); - return; - } - if (dist < -light->radius) - { - R_MarkLights (light, bit, node->children[1]); - return; - } - -// mark the polygons - surf = cl.worldmodel->surfaces + node->firstsurface; - for (i=0 ; inumsurfaces ; i++, surf++) - { - if (surf->dlightframe != r_dlightframecount) - { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; - } - surf->dlightbits |= bit; - } - - R_MarkLights (light, bit, node->children[0]); - R_MarkLights (light, bit, node->children[1]); -} - - -/* -============= -R_PushDlights -============= -*/ -void R_PushDlights (void) -{ - int i; - dlight_t *l; - - r_dlightframecount = r_framecount + 1; // because the count hasn't - // advanced yet for this frame - l = cl_dlights; - - for (i=0 ; idie < cl.time || !l->radius) - continue; - R_MarkLights ( l, 1<nodes ); - } -} - - -/* -============================================================================= - -LIGHT SAMPLING - -============================================================================= -*/ - -int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) -{ - int r; - float front, back, frac; - int side; - mplane_t *plane; - vec3_t mid; - msurface_t *surf; - int s, t, ds, dt; - int i; - mtexinfo_t *tex; - byte *lightmap; - unsigned scale; - int maps; - - if (node->contents < 0) - return -1; // didn't hit anything - -// calculate mid point - -// FIXME: optimize for axial - plane = node->plane; - front = DotProduct (start, plane->normal) - plane->dist; - back = DotProduct (end, plane->normal) - plane->dist; - side = front < 0; - - if ( (back < 0) == side) - return RecursiveLightPoint (node->children[side], start, end); - - frac = front / (front-back); - mid[0] = start[0] + (end[0] - start[0])*frac; - mid[1] = start[1] + (end[1] - start[1])*frac; - mid[2] = start[2] + (end[2] - start[2])*frac; - -// go down front side - r = RecursiveLightPoint (node->children[side], start, mid); - if (r >= 0) - return r; // hit something - - if ( (back < 0) == side ) - return -1; // didn't hit anuthing - -// check for impact on this node - - surf = cl.worldmodel->surfaces + node->firstsurface; - for (i=0 ; inumsurfaces ; i++, surf++) - { - if (surf->flags & SURF_DRAWTILED) - continue; // no lightmaps - - tex = surf->texinfo; - - s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; - t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; - - if (s < surf->texturemins[0] || - t < surf->texturemins[1]) - continue; - - ds = s - surf->texturemins[0]; - dt = t - surf->texturemins[1]; - - if ( ds > surf->extents[0] || dt > surf->extents[1] ) - continue; - - if (!surf->samples) - return 0; - - ds >>= 4; - dt >>= 4; - - lightmap = surf->samples; - r = 0; - if (lightmap) - { - - lightmap += dt * ((surf->extents[0]>>4)+1) + ds; - - for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; - maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]; - r += *lightmap * scale; - lightmap += ((surf->extents[0]>>4)+1) * - ((surf->extents[1]>>4)+1); - } - - r >>= 8; - } - - return r; - } - -// go down back side - return RecursiveLightPoint (node->children[!side], mid, end); -} - -int R_LightPoint (vec3_t p) -{ - vec3_t end; - int r; - - if (!cl.worldmodel->lightdata) - return 255; - - end[0] = p[0]; - end[1] = p[1]; - end[2] = p[2] - 2048; - - r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); - - if (r == -1) - r = 0; - - if (r < r_refdef.ambientlight) - r = r_refdef.ambientlight; - - return r; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_light.c + +#include "quakedef.h" +#include "r_local.h" + +int r_dlightframecount; + + +/* +================== +R_AnimateLight +================== +*/ +void R_AnimateLight (void) +{ + int i,j,k; + +// +// light animations +// 'm' is normal light, 'a' is no light, 'z' is double bright + i = (int)(cl.time*10); + for (j=0 ; jcontents < 0) + return; + + splitplane = node->plane; + dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; + + if (dist > light->radius) + { + R_MarkLights (light, bit, node->children[0]); + return; + } + if (dist < -light->radius) + { + R_MarkLights (light, bit, node->children[1]); + return; + } + +// mark the polygons + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + if (surf->dlightframe != r_dlightframecount) + { + surf->dlightbits = 0; + surf->dlightframe = r_dlightframecount; + } + surf->dlightbits |= bit; + } + + R_MarkLights (light, bit, node->children[0]); + R_MarkLights (light, bit, node->children[1]); +} + + +/* +============= +R_PushDlights +============= +*/ +void R_PushDlights (void) +{ + int i; + dlight_t *l; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + l = cl_dlights; + + for (i=0 ; idie < cl.time || !l->radius) + continue; + R_MarkLights ( l, 1<nodes ); + } +} + + +/* +============================================================================= + +LIGHT SAMPLING + +============================================================================= +*/ + +int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) +{ + int r; + float front, back, frac; + int side; + mplane_t *plane; + vec3_t mid; + msurface_t *surf; + int s, t, ds, dt; + int i; + mtexinfo_t *tex; + byte *lightmap; + unsigned scale; + int maps; + + if (node->contents < 0) + return -1; // didn't hit anything + +// calculate mid point + +// FIXME: optimize for axial + plane = node->plane; + front = DotProduct (start, plane->normal) - plane->dist; + back = DotProduct (end, plane->normal) - plane->dist; + side = front < 0; + + if ( (back < 0) == side) + return RecursiveLightPoint (node->children[side], start, end); + + frac = front / (front-back); + mid[0] = start[0] + (end[0] - start[0])*frac; + mid[1] = start[1] + (end[1] - start[1])*frac; + mid[2] = start[2] + (end[2] - start[2])*frac; + +// go down front side + r = RecursiveLightPoint (node->children[side], start, mid); + if (r >= 0) + return r; // hit something + + if ( (back < 0) == side ) + return -1; // didn't hit anuthing + +// check for impact on this node + + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + if (surf->flags & SURF_DRAWTILED) + continue; // no lightmaps + + tex = surf->texinfo; + + s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; + t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; + + if (s < surf->texturemins[0] || + t < surf->texturemins[1]) + continue; + + ds = s - surf->texturemins[0]; + dt = t - surf->texturemins[1]; + + if ( ds > surf->extents[0] || dt > surf->extents[1] ) + continue; + + if (!surf->samples) + return 0; + + ds >>= 4; + dt >>= 4; + + lightmap = surf->samples; + r = 0; + if (lightmap) + { + + lightmap += dt * ((surf->extents[0]>>4)+1) + ds; + + for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]; + r += *lightmap * scale; + lightmap += ((surf->extents[0]>>4)+1) * + ((surf->extents[1]>>4)+1); + } + + r >>= 8; + } + + return r; + } + +// go down back side + return RecursiveLightPoint (node->children[!side], mid, end); +} + +int R_LightPoint (vec3_t p) +{ + vec3_t end; + int r; + + if (!cl.worldmodel->lightdata) + return 255; + + end[0] = p[0]; + end[1] = p[1]; + end[2] = p[2] - 2048; + + r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); + + if (r == -1) + r = 0; + + if (r < r_refdef.ambientlight) + r = r_refdef.ambientlight; + + return r; +} + diff --git a/WinQuake/r_local.h b/WinQuake/r_local.h index e75f597..779acce 100644 --- a/WinQuake/r_local.h +++ b/WinQuake/r_local.h @@ -1,316 +1,316 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_local.h -- private refresh defs - -#ifndef GLQUAKE -#include "r_shared.h" - -#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) - // normalizing factor so player model works out to about - // 1 pixel per triangle - -#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox () - // if bbox is trivially rejected - -//=========================================================================== -// viewmodel lighting - -typedef struct { - int ambientlight; - int shadelight; - float *plightvec; -} alight_t; - -//=========================================================================== -// clipped bmodel edges - -typedef struct bedge_s -{ - mvertex_t *v[2]; - struct bedge_s *pnext; -} bedge_t; - -typedef struct { - float fv[3]; // viewspace x, y -} auxvert_t; - -//=========================================================================== - -extern cvar_t r_draworder; -extern cvar_t r_speeds; -extern cvar_t r_timegraph; -extern cvar_t r_graphheight; -extern cvar_t r_clearcolor; -extern cvar_t r_waterwarp; -extern cvar_t r_fullbright; -extern cvar_t r_drawentities; -extern cvar_t r_aliasstats; -extern cvar_t r_dspeeds; -extern cvar_t r_drawflat; -extern cvar_t r_ambient; -extern cvar_t r_reportsurfout; -extern cvar_t r_maxsurfs; -extern cvar_t r_numsurfs; -extern cvar_t r_reportedgeout; -extern cvar_t r_maxedges; -extern cvar_t r_numedges; - -#define XCENTERING (1.0 / 2.0) -#define YCENTERING (1.0 / 2.0) - -#define CLIP_EPSILON 0.001 - -#define BACKFACE_EPSILON 0.01 - -//=========================================================================== - -#define DIST_NOT_SET 98765 - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct clipplane_s -{ - vec3_t normal; - float dist; - struct clipplane_s *next; - byte leftedge; - byte rightedge; - byte reserved[2]; -} clipplane_t; - -extern clipplane_t view_clipplanes[4]; - -//============================================================================= - -void R_RenderWorld (void); - -//============================================================================= - -extern mplane_t screenedge[4]; - -extern vec3_t r_origin; - -extern vec3_t r_entorigin; - -extern float screenAspect; -extern float verticalFieldOfView; -extern float xOrigin, yOrigin; - -extern int r_visframecount; - -//============================================================================= - -extern int vstartscan; - - -void R_ClearPolyList (void); -void R_DrawPolyList (void); - -// -// current entity info -// -extern qboolean insubmodel; -extern vec3_t r_worldmodelorg; - - -void R_DrawSprite (void); -void R_RenderFace (msurface_t *fa, int clipflags); -void R_RenderPoly (msurface_t *fa, int clipflags); -void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); -void R_TransformPlane (mplane_t *p, float *normal, float *dist); -void R_TransformFrustum (void); -void R_SetSkyFrame (void); -void R_DrawSurfaceBlock16 (void); -void R_DrawSurfaceBlock8 (void); -texture_t *R_TextureAnimation (texture_t *base); - -#if id386 - -void R_DrawSurfaceBlock8_mip0 (void); -void R_DrawSurfaceBlock8_mip1 (void); -void R_DrawSurfaceBlock8_mip2 (void); -void R_DrawSurfaceBlock8_mip3 (void); - -#endif - -void R_GenSkyTile (void *pdest); -void R_GenSkyTile16 (void *pdest); -void R_Surf8Patch (void); -void R_Surf16Patch (void); -void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags); -void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel); - -void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); -surf_t *R_GetSurf (void); -void R_AliasDrawModel (alight_t *plighting); -void R_BeginEdgeFrame (void); -void R_ScanEdges (void); -void D_DrawSurfaces (void); -void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist); -void R_StepActiveU (edge_t *pedge); -void R_RemoveEdges (edge_t *pedge); - -extern void R_Surf8Start (void); -extern void R_Surf8End (void); -extern void R_Surf16Start (void); -extern void R_Surf16End (void); -extern void R_EdgeCodeStart (void); -extern void R_EdgeCodeEnd (void); - -extern void R_RotateBmodel (void); - -extern int c_faceclip; -extern int r_polycount; -extern int r_wholepolycount; - -extern model_t *cl_worldmodel; - -extern int *pfrustum_indexes[4]; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -#define NEAR_CLIP 0.01 - -extern int ubasestep, errorterm, erroradjustup, erroradjustdown; -extern int vstartscan; - -extern fixed16_t sadjust, tadjust; -extern fixed16_t bbextents, bbextentt; - -#define MAXBVERTINDEXES 1000 // new clipped vertices when clipping bmodels - // to the world BSP -extern mvertex_t *r_ptverts, *r_ptvertsmax; - -extern vec3_t sbaseaxis[3], tbaseaxis[3]; -extern float entity_rotation[3][3]; - -extern int reinit_surfcache; - -extern int r_currentkey; -extern int r_currentbkey; - -typedef struct btofpoly_s { - int clipflags; - msurface_t *psurf; -} btofpoly_t; - -#define MAX_BTOFPOLYS 5000 // FIXME: tune this - -extern int numbtofpolys; -extern btofpoly_t *pbtofpolys; - -void R_InitTurb (void); -void R_ZDrawSubmodelPolys (model_t *clmodel); - -//========================================================= -// Alias models -//========================================================= - -#define MAXALIASVERTS 2000 // TODO: tune this -#define ALIAS_Z_CLIP_PLANE 5 - -extern int numverts; -extern int a_skinwidth; -extern mtriangle_t *ptriangles; -extern int numtriangles; -extern aliashdr_t *paliashdr; -extern mdl_t *pmdl; -extern float leftclip, topclip, rightclip, bottomclip; -extern int r_acliptype; -extern finalvert_t *pfinalverts; -extern auxvert_t *pauxverts; - -qboolean R_AliasCheckBBox (void); - -//========================================================= -// turbulence stuff - -#define AMP 8*0x10000 -#define AMP2 3 -#define SPEED 20 - -//========================================================= -// particle stuff - -void R_DrawParticles (void); -void R_InitParticles (void); -void R_ClearParticles (void); -void R_ReadPointFile_f (void); -void R_SurfacePatch (void); - -extern int r_amodels_drawn; -extern edge_t *auxedges; -extern int r_numallocatededges; -extern edge_t *r_edges, *edge_p, *edge_max; - -extern edge_t *newedges[MAXHEIGHT]; -extern edge_t *removeedges[MAXHEIGHT]; - -extern int screenwidth; - -// FIXME: make stack vars when debugging done -extern edge_t edge_head; -extern edge_t edge_tail; -extern edge_t edge_aftertail; -extern int r_bmodelactive; -extern vrect_t *pconupdate; - -extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; -extern float r_aliastransition, r_resfudge; - -extern int r_outofsurfaces; -extern int r_outofedges; - -extern mvertex_t *r_pcurrentvertbase; -extern int r_maxvalidedgeoffset; - -void R_AliasClipTriangle (mtriangle_t *ptri); - -extern float r_time1; -extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; -extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; -extern int r_frustum_indexes[4*6]; -extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; -extern qboolean r_surfsonstack; -extern cshift_t cshift_water; -extern qboolean r_dowarpold, r_viewchanged; - -extern mleaf_t *r_viewleaf, *r_oldviewleaf; - -extern vec3_t r_emins, r_emaxs; -extern mnode_t *r_pefragtopnode; -extern int r_clipflags; -extern int r_dlightframecount; -extern qboolean r_fov_greater_than_90; - -void R_StoreEfrags (efrag_t **ppefrag); -void R_TimeRefresh_f (void); -void R_TimeGraph (void); -void R_PrintAliasStats (void); -void R_PrintTimes (void); -void R_PrintDSpeeds (void); -void R_AnimateLight (void); -int R_LightPoint (vec3_t p); -void R_SetupFrame (void); -void R_cshift_f (void); -void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); -void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); -void R_SplitEntityOnNode2 (mnode_t *node); -void R_MarkLights (dlight_t *light, int bit, mnode_t *node); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_local.h -- private refresh defs + +#ifndef GLQUAKE +#include "r_shared.h" + +#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) + // normalizing factor so player model works out to about + // 1 pixel per triangle + +#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox () + // if bbox is trivially rejected + +//=========================================================================== +// viewmodel lighting + +typedef struct { + int ambientlight; + int shadelight; + float *plightvec; +} alight_t; + +//=========================================================================== +// clipped bmodel edges + +typedef struct bedge_s +{ + mvertex_t *v[2]; + struct bedge_s *pnext; +} bedge_t; + +typedef struct { + float fv[3]; // viewspace x, y +} auxvert_t; + +//=========================================================================== + +extern cvar_t r_draworder; +extern cvar_t r_speeds; +extern cvar_t r_timegraph; +extern cvar_t r_graphheight; +extern cvar_t r_clearcolor; +extern cvar_t r_waterwarp; +extern cvar_t r_fullbright; +extern cvar_t r_drawentities; +extern cvar_t r_aliasstats; +extern cvar_t r_dspeeds; +extern cvar_t r_drawflat; +extern cvar_t r_ambient; +extern cvar_t r_reportsurfout; +extern cvar_t r_maxsurfs; +extern cvar_t r_numsurfs; +extern cvar_t r_reportedgeout; +extern cvar_t r_maxedges; +extern cvar_t r_numedges; + +#define XCENTERING (1.0 / 2.0) +#define YCENTERING (1.0 / 2.0) + +#define CLIP_EPSILON 0.001 + +#define BACKFACE_EPSILON 0.01 + +//=========================================================================== + +#define DIST_NOT_SET 98765 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct clipplane_s +{ + vec3_t normal; + float dist; + struct clipplane_s *next; + byte leftedge; + byte rightedge; + byte reserved[2]; +} clipplane_t; + +extern clipplane_t view_clipplanes[4]; + +//============================================================================= + +void R_RenderWorld (void); + +//============================================================================= + +extern mplane_t screenedge[4]; + +extern vec3_t r_origin; + +extern vec3_t r_entorigin; + +extern float screenAspect; +extern float verticalFieldOfView; +extern float xOrigin, yOrigin; + +extern int r_visframecount; + +//============================================================================= + +extern int vstartscan; + + +void R_ClearPolyList (void); +void R_DrawPolyList (void); + +// +// current entity info +// +extern qboolean insubmodel; +extern vec3_t r_worldmodelorg; + + +void R_DrawSprite (void); +void R_RenderFace (msurface_t *fa, int clipflags); +void R_RenderPoly (msurface_t *fa, int clipflags); +void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); +void R_TransformPlane (mplane_t *p, float *normal, float *dist); +void R_TransformFrustum (void); +void R_SetSkyFrame (void); +void R_DrawSurfaceBlock16 (void); +void R_DrawSurfaceBlock8 (void); +texture_t *R_TextureAnimation (texture_t *base); + +#if id386 + +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); + +#endif + +void R_GenSkyTile (void *pdest); +void R_GenSkyTile16 (void *pdest); +void R_Surf8Patch (void); +void R_Surf16Patch (void); +void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags); +void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel); + +void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); +surf_t *R_GetSurf (void); +void R_AliasDrawModel (alight_t *plighting); +void R_BeginEdgeFrame (void); +void R_ScanEdges (void); +void D_DrawSurfaces (void); +void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist); +void R_StepActiveU (edge_t *pedge); +void R_RemoveEdges (edge_t *pedge); + +extern void R_Surf8Start (void); +extern void R_Surf8End (void); +extern void R_Surf16Start (void); +extern void R_Surf16End (void); +extern void R_EdgeCodeStart (void); +extern void R_EdgeCodeEnd (void); + +extern void R_RotateBmodel (void); + +extern int c_faceclip; +extern int r_polycount; +extern int r_wholepolycount; + +extern model_t *cl_worldmodel; + +extern int *pfrustum_indexes[4]; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +#define NEAR_CLIP 0.01 + +extern int ubasestep, errorterm, erroradjustup, erroradjustdown; +extern int vstartscan; + +extern fixed16_t sadjust, tadjust; +extern fixed16_t bbextents, bbextentt; + +#define MAXBVERTINDEXES 1000 // new clipped vertices when clipping bmodels + // to the world BSP +extern mvertex_t *r_ptverts, *r_ptvertsmax; + +extern vec3_t sbaseaxis[3], tbaseaxis[3]; +extern float entity_rotation[3][3]; + +extern int reinit_surfcache; + +extern int r_currentkey; +extern int r_currentbkey; + +typedef struct btofpoly_s { + int clipflags; + msurface_t *psurf; +} btofpoly_t; + +#define MAX_BTOFPOLYS 5000 // FIXME: tune this + +extern int numbtofpolys; +extern btofpoly_t *pbtofpolys; + +void R_InitTurb (void); +void R_ZDrawSubmodelPolys (model_t *clmodel); + +//========================================================= +// Alias models +//========================================================= + +#define MAXALIASVERTS 2000 // TODO: tune this +#define ALIAS_Z_CLIP_PLANE 5 + +extern int numverts; +extern int a_skinwidth; +extern mtriangle_t *ptriangles; +extern int numtriangles; +extern aliashdr_t *paliashdr; +extern mdl_t *pmdl; +extern float leftclip, topclip, rightclip, bottomclip; +extern int r_acliptype; +extern finalvert_t *pfinalverts; +extern auxvert_t *pauxverts; + +qboolean R_AliasCheckBBox (void); + +//========================================================= +// turbulence stuff + +#define AMP 8*0x10000 +#define AMP2 3 +#define SPEED 20 + +//========================================================= +// particle stuff + +void R_DrawParticles (void); +void R_InitParticles (void); +void R_ClearParticles (void); +void R_ReadPointFile_f (void); +void R_SurfacePatch (void); + +extern int r_amodels_drawn; +extern edge_t *auxedges; +extern int r_numallocatededges; +extern edge_t *r_edges, *edge_p, *edge_max; + +extern edge_t *newedges[MAXHEIGHT]; +extern edge_t *removeedges[MAXHEIGHT]; + +extern int screenwidth; + +// FIXME: make stack vars when debugging done +extern edge_t edge_head; +extern edge_t edge_tail; +extern edge_t edge_aftertail; +extern int r_bmodelactive; +extern vrect_t *pconupdate; + +extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; +extern float r_aliastransition, r_resfudge; + +extern int r_outofsurfaces; +extern int r_outofedges; + +extern mvertex_t *r_pcurrentvertbase; +extern int r_maxvalidedgeoffset; + +void R_AliasClipTriangle (mtriangle_t *ptri); + +extern float r_time1; +extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; +extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; +extern int r_frustum_indexes[4*6]; +extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +extern qboolean r_surfsonstack; +extern cshift_t cshift_water; +extern qboolean r_dowarpold, r_viewchanged; + +extern mleaf_t *r_viewleaf, *r_oldviewleaf; + +extern vec3_t r_emins, r_emaxs; +extern mnode_t *r_pefragtopnode; +extern int r_clipflags; +extern int r_dlightframecount; +extern qboolean r_fov_greater_than_90; + +void R_StoreEfrags (efrag_t **ppefrag); +void R_TimeRefresh_f (void); +void R_TimeGraph (void); +void R_PrintAliasStats (void); +void R_PrintTimes (void); +void R_PrintDSpeeds (void); +void R_AnimateLight (void); +int R_LightPoint (vec3_t p); +void R_SetupFrame (void); +void R_cshift_f (void); +void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); +void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); +void R_SplitEntityOnNode2 (mnode_t *node); +void R_MarkLights (dlight_t *light, int bit, mnode_t *node); + #endif \ No newline at end of file diff --git a/WinQuake/r_main.c b/WinQuake/r_main.c index 3fe5146..e0e06ba 100644 --- a/WinQuake/r_main.c +++ b/WinQuake/r_main.c @@ -1,1085 +1,1085 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_main.c - -#include "quakedef.h" -#include "r_local.h" - -//define PASSAGES - -void *colormap; -vec3_t viewlightvec; -alight_t r_viewlighting = {128, 192, viewlightvec}; -float r_time1; -int r_numallocatededges; -qboolean r_drawpolys; -qboolean r_drawculledpolys; -qboolean r_worldpolysbacktofront; -qboolean r_recursiveaffinetriangles = true; -int r_pixbytes = 1; -float r_aliasuvscale = 1.0; -int r_outofsurfaces; -int r_outofedges; - -qboolean r_dowarp, r_dowarpold, r_viewchanged; - -int numbtofpolys; -btofpoly_t *pbtofpolys; -mvertex_t *r_pcurrentvertbase; - -int c_surf; -int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; -qboolean r_surfsonstack; -int r_clipflags; - -byte *r_warpbuffer; - -byte *r_stack_start; - -qboolean r_fov_greater_than_90; - -// -// view origin -// -vec3_t vup, base_vup; -vec3_t vpn, base_vpn; -vec3_t vright, base_vright; -vec3_t r_origin; - -// -// screen size info -// -refdef_t r_refdef; -float xcenter, ycenter; -float xscale, yscale; -float xscaleinv, yscaleinv; -float xscaleshrink, yscaleshrink; -float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; - -int screenwidth; - -float pixelAspect; -float screenAspect; -float verticalFieldOfView; -float xOrigin, yOrigin; - -mplane_t screenedge[4]; - -// -// refresh flags -// -int r_framecount = 1; // so frame counts initialized to 0 don't match -int r_visframecount; -int d_spanpixcount; -int r_polycount; -int r_drawnpolycount; -int r_wholepolycount; - -#define VIEWMODNAME_LENGTH 256 -char viewmodname[VIEWMODNAME_LENGTH+1]; -int modcount; - -int *pfrustum_indexes[4]; -int r_frustum_indexes[4*6]; - -int reinit_surfcache = 1; // if 1, surface cache is currently empty and - // must be reinitialized for current cache size - -mleaf_t *r_viewleaf, *r_oldviewleaf; - -texture_t *r_notexture_mip; - -float r_aliastransition, r_resfudge; - -int d_lightstylevalue[256]; // 8.8 fraction of base light value - -float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; -float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; - -void R_MarkLeaves (void); - -cvar_t r_draworder = {"r_draworder","0"}; -cvar_t r_speeds = {"r_speeds","0"}; -cvar_t r_timegraph = {"r_timegraph","0"}; -cvar_t r_graphheight = {"r_graphheight","10"}; -cvar_t r_clearcolor = {"r_clearcolor","2"}; -cvar_t r_waterwarp = {"r_waterwarp","1"}; -cvar_t r_fullbright = {"r_fullbright","0"}; -cvar_t r_drawentities = {"r_drawentities","1"}; -cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; -cvar_t r_aliasstats = {"r_polymodelstats","0"}; -cvar_t r_dspeeds = {"r_dspeeds","0"}; -cvar_t r_drawflat = {"r_drawflat", "0"}; -cvar_t r_ambient = {"r_ambient", "0"}; -cvar_t r_reportsurfout = {"r_reportsurfout", "0"}; -cvar_t r_maxsurfs = {"r_maxsurfs", "0"}; -cvar_t r_numsurfs = {"r_numsurfs", "0"}; -cvar_t r_reportedgeout = {"r_reportedgeout", "0"}; -cvar_t r_maxedges = {"r_maxedges", "0"}; -cvar_t r_numedges = {"r_numedges", "0"}; -cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; -cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; - -extern cvar_t scr_fov; - -void CreatePassages (void); -void SetVisibilityByPassages (void); - -/* -================== -R_InitTextures -================== -*/ -void R_InitTextures (void) -{ - int x,y, m; - byte *dest; - -// create a simple checkerboard texture for the default - r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); - - r_notexture_mip->width = r_notexture_mip->height = 16; - r_notexture_mip->offsets[0] = sizeof(texture_t); - r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; - r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; - r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; - - for (m=0 ; m<4 ; m++) - { - dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; - for (y=0 ; y< (16>>m) ; y++) - for (x=0 ; x< (16>>m) ; x++) - { - if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) - *dest++ = 0; - else - *dest++ = 0xff; - } - } -} - -/* -=============== -R_Init -=============== -*/ -void R_Init (void) -{ - int dummy; - -// get stack position so we can guess if we are going to overflow - r_stack_start = (byte *)&dummy; - - R_InitTurb (); - - Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); - Cmd_AddCommand ("pointfile", R_ReadPointFile_f); - - Cvar_RegisterVariable (&r_draworder); - Cvar_RegisterVariable (&r_speeds); - Cvar_RegisterVariable (&r_timegraph); - Cvar_RegisterVariable (&r_graphheight); - Cvar_RegisterVariable (&r_drawflat); - Cvar_RegisterVariable (&r_ambient); - Cvar_RegisterVariable (&r_clearcolor); - Cvar_RegisterVariable (&r_waterwarp); - Cvar_RegisterVariable (&r_fullbright); - Cvar_RegisterVariable (&r_drawentities); - Cvar_RegisterVariable (&r_drawviewmodel); - Cvar_RegisterVariable (&r_aliasstats); - Cvar_RegisterVariable (&r_dspeeds); - Cvar_RegisterVariable (&r_reportsurfout); - Cvar_RegisterVariable (&r_maxsurfs); - Cvar_RegisterVariable (&r_numsurfs); - Cvar_RegisterVariable (&r_reportedgeout); - Cvar_RegisterVariable (&r_maxedges); - Cvar_RegisterVariable (&r_numedges); - Cvar_RegisterVariable (&r_aliastransbase); - Cvar_RegisterVariable (&r_aliastransadj); - - Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); - Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); - - view_clipplanes[0].leftedge = true; - view_clipplanes[1].rightedge = true; - view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = - view_clipplanes[3].leftedge = false; - view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = - view_clipplanes[3].rightedge = false; - - r_refdef.xOrigin = XCENTERING; - r_refdef.yOrigin = YCENTERING; - - R_InitParticles (); - -// TODO: collect 386-specific code in one place -#if id386 - Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, - (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); -#endif // id386 - - D_Init (); -} - -/* -=============== -R_NewMap -=============== -*/ -void R_NewMap (void) -{ - int i; - -// clear out efrags in case the level hasn't been reloaded -// FIXME: is this one short? - for (i=0 ; inumleafs ; i++) - cl.worldmodel->leafs[i].efrags = NULL; - - r_viewleaf = NULL; - R_ClearParticles (); - - r_cnumsurfs = r_maxsurfs.value; - - if (r_cnumsurfs <= MINSURFACES) - r_cnumsurfs = MINSURFACES; - - if (r_cnumsurfs > NUMSTACKSURFACES) - { - surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); - surface_p = surfaces; - surf_max = &surfaces[r_cnumsurfs]; - r_surfsonstack = false; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - surfaces--; - R_SurfacePatch (); - } - else - { - r_surfsonstack = true; - } - - r_maxedgesseen = 0; - r_maxsurfsseen = 0; - - r_numallocatededges = r_maxedges.value; - - if (r_numallocatededges < MINEDGES) - r_numallocatededges = MINEDGES; - - if (r_numallocatededges <= NUMSTACKEDGES) - { - auxedges = NULL; - } - else - { - auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), - "edges"); - } - - r_dowarpold = false; - r_viewchanged = false; -#ifdef PASSAGES -CreatePassages (); -#endif -} - - -/* -=============== -R_SetVrect -=============== -*/ -void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) -{ - int h; - float size; - - size = scr_viewsize.value > 100 ? 100 : scr_viewsize.value; - if (cl.intermission) - { - size = 100; - lineadj = 0; - } - size /= 100; - - h = pvrectin->height - lineadj; - pvrect->width = pvrectin->width * size; - if (pvrect->width < 96) - { - size = 96.0 / pvrectin->width; - pvrect->width = 96; // min for icons - } - pvrect->width &= ~7; - pvrect->height = pvrectin->height * size; - if (pvrect->height > pvrectin->height - lineadj) - pvrect->height = pvrectin->height - lineadj; - - pvrect->height &= ~1; - - pvrect->x = (pvrectin->width - pvrect->width)/2; - pvrect->y = (h - pvrect->height)/2; - - { - if (lcd_x.value) - { - pvrect->y >>= 1; - pvrect->height >>= 1; - } - } -} - - -/* -=============== -R_ViewChanged - -Called every time the vid structure or r_refdef changes. -Guaranteed to be called before the first refresh -=============== -*/ -void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) -{ - int i; - float res_scale; - - r_viewchanged = true; - - R_SetVrect (pvrect, &r_refdef.vrect, lineadj); - - r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); - r_refdef.fvrectx = (float)r_refdef.vrect.x; - r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; - r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; - r_refdef.fvrecty = (float)r_refdef.vrect.y; - r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; - r_refdef.fvrectright = (float)r_refdef.vrectright; - r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; - r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; - r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; - r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; - - r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); - r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); - r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); - r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); - r_refdef.aliasvrectright = r_refdef.aliasvrect.x + - r_refdef.aliasvrect.width; - r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + - r_refdef.aliasvrect.height; - - pixelAspect = aspect; - xOrigin = r_refdef.xOrigin; - yOrigin = r_refdef.yOrigin; - - screenAspect = r_refdef.vrect.width*pixelAspect / - r_refdef.vrect.height; -// 320*200 1.0 pixelAspect = 1.6 screenAspect -// 320*240 1.0 pixelAspect = 1.3333 screenAspect -// proper 320*200 pixelAspect = 0.8333333 - - verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; - -// values for perspective projection -// if math were exact, the values would range from 0.5 to to range+0.5 -// hopefully they wll be in the 0.000001 to range+.999999 and truncate -// the polygon rasterization will never render in the first row or column -// but will definately render in the [range] row and column, so adjust the -// buffer origin to get an exact edge to edge fill - xcenter = ((float)r_refdef.vrect.width * XCENTERING) + - r_refdef.vrect.x - 0.5; - aliasxcenter = xcenter * r_aliasuvscale; - ycenter = ((float)r_refdef.vrect.height * YCENTERING) + - r_refdef.vrect.y - 0.5; - aliasycenter = ycenter * r_aliasuvscale; - - xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; - aliasxscale = xscale * r_aliasuvscale; - xscaleinv = 1.0 / xscale; - yscale = xscale * pixelAspect; - aliasyscale = yscale * r_aliasuvscale; - yscaleinv = 1.0 / yscale; - xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; - yscaleshrink = xscaleshrink*pixelAspect; - -// left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); - screenedge[0].normal[1] = 0; - screenedge[0].normal[2] = 1; - screenedge[0].type = PLANE_ANYZ; - -// right side clip - screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); - screenedge[1].normal[1] = 0; - screenedge[1].normal[2] = 1; - screenedge[1].type = PLANE_ANYZ; - -// top side clip - screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); - screenedge[2].normal[2] = 1; - screenedge[2].type = PLANE_ANYZ; - -// bottom side clip - screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); - screenedge[3].normal[2] = 1; - screenedge[3].type = PLANE_ANYZ; - - for (i=0 ; i<4 ; i++) - VectorNormalize (screenedge[i].normal); - - res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * - (2.0 / r_refdef.horizontalFieldOfView); - r_aliastransition = r_aliastransbase.value * res_scale; - r_resfudge = r_aliastransadj.value * res_scale; - - if (scr_fov.value <= 90.0) - r_fov_greater_than_90 = false; - else - r_fov_greater_than_90 = true; - -// TODO: collect 386-specific code in one place -#if id386 - if (r_pixbytes == 1) - { - Sys_MakeCodeWriteable ((long)R_Surf8Start, - (long)R_Surf8End - (long)R_Surf8Start); - colormap = vid.colormap; - R_Surf8Patch (); - } - else - { - Sys_MakeCodeWriteable ((long)R_Surf16Start, - (long)R_Surf16End - (long)R_Surf16Start); - colormap = vid.colormap16; - R_Surf16Patch (); - } -#endif // id386 - - D_ViewChanged (); -} - - -/* -=============== -R_MarkLeaves -=============== -*/ -void R_MarkLeaves (void) -{ - byte *vis; - mnode_t *node; - int i; - - if (r_oldviewleaf == r_viewleaf) - return; - - r_visframecount++; - r_oldviewleaf = r_viewleaf; - - vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - - for (i=0 ; inumleafs ; i++) - { - if (vis[i>>3] & (1<<(i&7))) - { - node = (mnode_t *)&cl.worldmodel->leafs[i+1]; - do - { - if (node->visframe == r_visframecount) - break; - node->visframe = r_visframecount; - node = node->parent; - } while (node); - } - } -} - - -/* -============= -R_DrawEntitiesOnList -============= -*/ -void R_DrawEntitiesOnList (void) -{ - int i, j; - int lnum; - alight_t lighting; -// FIXME: remove and do real lighting - float lightvec[3] = {-1, 0, 0}; - vec3_t dist; - float add; - - if (!r_drawentities.value) - return; - - for (i=0 ; imodel->type) - { - case mod_sprite: - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - R_DrawSprite (); - break; - - case mod_alias: - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // see if the bounding box lets us trivially reject, also sets - // trivial accept status - if (R_AliasCheckBBox ()) - { - j = R_LightPoint (currententity->origin); - - lighting.ambientlight = j; - lighting.shadelight = j; - - lighting.plightvec = lightvec; - - for (lnum=0 ; lnum= cl.time) - { - VectorSubtract (currententity->origin, - cl_dlights[lnum].origin, - dist); - add = cl_dlights[lnum].radius - Length(dist); - - if (add > 0) - lighting.ambientlight += add; - } - } - - // clamp lighting so it doesn't overbright as much - if (lighting.ambientlight > 128) - lighting.ambientlight = 128; - if (lighting.ambientlight + lighting.shadelight > 192) - lighting.shadelight = 192 - lighting.ambientlight; - - R_AliasDrawModel (&lighting); - } - - break; - - default: - break; - } - } -} - -/* -============= -R_DrawViewModel -============= -*/ -void R_DrawViewModel (void) -{ -// FIXME: remove and do real lighting - float lightvec[3] = {-1, 0, 0}; - int j; - int lnum; - vec3_t dist; - float add; - dlight_t *dl; - - if (!r_drawviewmodel.value || r_fov_greater_than_90) - return; - - if (cl.items & IT_INVISIBILITY) - return; - - if (cl.stats[STAT_HEALTH] <= 0) - return; - - currententity = &cl.viewent; - if (!currententity->model) - return; - - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - VectorCopy (vup, viewlightvec); - VectorInverse (viewlightvec); - - j = R_LightPoint (currententity->origin); - - if (j < 24) - j = 24; // allways give some light on gun - r_viewlighting.ambientlight = j; - r_viewlighting.shadelight = j; - -// add dynamic lights - for (lnum=0 ; lnumradius) - continue; - if (!dl->radius) - continue; - if (dl->die < cl.time) - continue; - - VectorSubtract (currententity->origin, dl->origin, dist); - add = dl->radius - Length(dist); - if (add > 0) - r_viewlighting.ambientlight += add; - } - -// clamp lighting so it doesn't overbright as much - if (r_viewlighting.ambientlight > 128) - r_viewlighting.ambientlight = 128; - if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) - r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; - - r_viewlighting.plightvec = lightvec; - -#ifdef QUAKE2 - cl.light_level = r_viewlighting.ambientlight; -#endif - - R_AliasDrawModel (&r_viewlighting); -} - - -/* -============= -R_BmodelCheckBBox -============= -*/ -int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) -{ - int i, *pindex, clipflags; - vec3_t acceptpt, rejectpt; - double d; - - clipflags = 0; - - if (currententity->angles[0] || currententity->angles[1] - || currententity->angles[2]) - { - for (i=0 ; i<4 ; i++) - { - d = DotProduct (currententity->origin, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d <= -clmodel->radius) - return BMODEL_FULLY_CLIPPED; - - if (d <= clmodel->radius) - clipflags |= (1<model->type) - { - case mod_brush: - - clmodel = currententity->model; - - // see if the bounding box lets us trivially reject, also sets - // trivial accept status - for (j=0 ; j<3 ; j++) - { - minmaxs[j] = currententity->origin[j] + - clmodel->mins[j]; - minmaxs[3+j] = currententity->origin[j] + - clmodel->maxs[j]; - } - - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); - - if (clipflags != BMODEL_FULLY_CLIPPED) - { - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - // FIXME: is this needed? - VectorCopy (modelorg, r_worldmodelorg); - - r_pcurrentvertbase = clmodel->vertexes; - - // FIXME: stop transforming twice - R_RotateBmodel (); - - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if (clmodel->firstmodelsurface != 0) - { - for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); - } - } - - // if the driver wants polygons, deliver those. Z-buffering is on - // at this point, so no clipping to the world tree is needed, just - // frustum clipping - if (r_drawpolys | r_drawculledpolys) - { - R_ZDrawSubmodelPolys (clmodel); - } - else - { - r_pefragtopnode = NULL; - - for (j=0 ; j<3 ; j++) - { - r_emins[j] = minmaxs[j]; - r_emaxs[j] = minmaxs[3+j]; - } - - R_SplitEntityOnNode2 (cl.worldmodel->nodes); - - if (r_pefragtopnode) - { - currententity->topnode = r_pefragtopnode; - - if (r_pefragtopnode->contents >= 0) - { - // not a leaf; has to be clipped to the world BSP - r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (clmodel); - } - else - { - // falls entirely in one leaf, so we just put all the - // edges in the edge list and let 1/z sorting handle - // drawing order - R_DrawSubmodelPolygons (clmodel, clipflags); - } - - currententity->topnode = NULL; - } - } - - // put back world rotation and frustum clipping - // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); - R_TransformFrustum (); - } - - break; - - default: - break; - } - } - - insubmodel = false; -} - - -/* -================ -R_EdgeDrawing -================ -*/ -void R_EdgeDrawing (void) -{ - edge_t ledges[NUMSTACKEDGES + - ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; - surf_t lsurfs[NUMSTACKSURFACES + - ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; - - if (auxedges) - { - r_edges = auxedges; - } - else - { - r_edges = (edge_t *) - (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - } - - if (r_surfsonstack) - { - surfaces = (surf_t *) - (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - surf_max = &surfaces[r_cnumsurfs]; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - surfaces--; - R_SurfacePatch (); - } - - R_BeginEdgeFrame (); - - if (r_dspeeds.value) - { - rw_time1 = Sys_FloatTime (); - } - - R_RenderWorld (); - - if (r_drawculledpolys) - R_ScanEdges (); - -// only the world can be drawn back to front with no z reads or compares, just -// z writes, so have the driver turn z compares on now - D_TurnZOn (); - - if (r_dspeeds.value) - { - rw_time2 = Sys_FloatTime (); - db_time1 = rw_time2; - } - - R_DrawBEntitiesOnList (); - - if (r_dspeeds.value) - { - db_time2 = Sys_FloatTime (); - se_time1 = db_time2; - } - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - if (!(r_drawpolys | r_drawculledpolys)) - R_ScanEdges (); -} - - -/* -================ -R_RenderView - -r_refdef must be set before the first call -================ -*/ -void R_RenderView_ (void) -{ - byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; - - r_warpbuffer = warpbuffer; - - if (r_timegraph.value || r_speeds.value || r_dspeeds.value) - r_time1 = Sys_FloatTime (); - - R_SetupFrame (); - -#ifdef PASSAGES -SetVisibilityByPassages (); -#else - R_MarkLeaves (); // done here so we know if we're in water -#endif - -// make FDIV fast. This reduces timing precision after we've been running for a -// while, so we don't do it globally. This also sets chop mode, and we do it -// here so that setup stuff like the refresh area calculations match what's -// done in screen.c - Sys_LowFPPrecision (); - - if (!cl_entities[0].model || !cl.worldmodel) - Sys_Error ("R_RenderView: NULL worldmodel"); - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - R_EdgeDrawing (); - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - if (r_dspeeds.value) - { - se_time2 = Sys_FloatTime (); - de_time1 = se_time2; - } - - R_DrawEntitiesOnList (); - - if (r_dspeeds.value) - { - de_time2 = Sys_FloatTime (); - dv_time1 = de_time2; - } - - R_DrawViewModel (); - - if (r_dspeeds.value) - { - dv_time2 = Sys_FloatTime (); - dp_time1 = Sys_FloatTime (); - } - - R_DrawParticles (); - - if (r_dspeeds.value) - dp_time2 = Sys_FloatTime (); - - if (r_dowarp) - D_WarpScreen (); - - V_SetContentsColor (r_viewleaf->contents); - - if (r_timegraph.value) - R_TimeGraph (); - - if (r_aliasstats.value) - R_PrintAliasStats (); - - if (r_speeds.value) - R_PrintTimes (); - - if (r_dspeeds.value) - R_PrintDSpeeds (); - - if (r_reportsurfout.value && r_outofsurfaces) - Con_Printf ("Short %d surfaces\n", r_outofsurfaces); - - if (r_reportedgeout.value && r_outofedges) - Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); - -// back to high floating-point precision - Sys_HighFPPrecision (); -} - -void R_RenderView (void) -{ - int dummy; - int delta; - - delta = (byte *)&dummy - r_stack_start; - if (delta < -10000 || delta > 10000) - Sys_Error ("R_RenderView: called without enough stack"); - - if ( Hunk_LowMark() & 3 ) - Sys_Error ("Hunk is missaligned"); - - if ( (long)(&dummy) & 3 ) - Sys_Error ("Stack is missaligned"); - - if ( (long)(&r_warpbuffer) & 3 ) - Sys_Error ("Globals are missaligned"); - - R_RenderView_ (); -} - -/* -================ -R_InitTurb -================ -*/ -void R_InitTurb (void) -{ - int i; - - for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++) - { - sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; - intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_main.c + +#include "quakedef.h" +#include "r_local.h" + +//define PASSAGES + +void *colormap; +vec3_t viewlightvec; +alight_t r_viewlighting = {128, 192, viewlightvec}; +float r_time1; +int r_numallocatededges; +qboolean r_drawpolys; +qboolean r_drawculledpolys; +qboolean r_worldpolysbacktofront; +qboolean r_recursiveaffinetriangles = true; +int r_pixbytes = 1; +float r_aliasuvscale = 1.0; +int r_outofsurfaces; +int r_outofedges; + +qboolean r_dowarp, r_dowarpold, r_viewchanged; + +int numbtofpolys; +btofpoly_t *pbtofpolys; +mvertex_t *r_pcurrentvertbase; + +int c_surf; +int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +qboolean r_surfsonstack; +int r_clipflags; + +byte *r_warpbuffer; + +byte *r_stack_start; + +qboolean r_fov_greater_than_90; + +// +// view origin +// +vec3_t vup, base_vup; +vec3_t vpn, base_vpn; +vec3_t vright, base_vright; +vec3_t r_origin; + +// +// screen size info +// +refdef_t r_refdef; +float xcenter, ycenter; +float xscale, yscale; +float xscaleinv, yscaleinv; +float xscaleshrink, yscaleshrink; +float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; + +int screenwidth; + +float pixelAspect; +float screenAspect; +float verticalFieldOfView; +float xOrigin, yOrigin; + +mplane_t screenedge[4]; + +// +// refresh flags +// +int r_framecount = 1; // so frame counts initialized to 0 don't match +int r_visframecount; +int d_spanpixcount; +int r_polycount; +int r_drawnpolycount; +int r_wholepolycount; + +#define VIEWMODNAME_LENGTH 256 +char viewmodname[VIEWMODNAME_LENGTH+1]; +int modcount; + +int *pfrustum_indexes[4]; +int r_frustum_indexes[4*6]; + +int reinit_surfcache = 1; // if 1, surface cache is currently empty and + // must be reinitialized for current cache size + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +texture_t *r_notexture_mip; + +float r_aliastransition, r_resfudge; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + +float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; +float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; + +void R_MarkLeaves (void); + +cvar_t r_draworder = {"r_draworder","0"}; +cvar_t r_speeds = {"r_speeds","0"}; +cvar_t r_timegraph = {"r_timegraph","0"}; +cvar_t r_graphheight = {"r_graphheight","10"}; +cvar_t r_clearcolor = {"r_clearcolor","2"}; +cvar_t r_waterwarp = {"r_waterwarp","1"}; +cvar_t r_fullbright = {"r_fullbright","0"}; +cvar_t r_drawentities = {"r_drawentities","1"}; +cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; +cvar_t r_aliasstats = {"r_polymodelstats","0"}; +cvar_t r_dspeeds = {"r_dspeeds","0"}; +cvar_t r_drawflat = {"r_drawflat", "0"}; +cvar_t r_ambient = {"r_ambient", "0"}; +cvar_t r_reportsurfout = {"r_reportsurfout", "0"}; +cvar_t r_maxsurfs = {"r_maxsurfs", "0"}; +cvar_t r_numsurfs = {"r_numsurfs", "0"}; +cvar_t r_reportedgeout = {"r_reportedgeout", "0"}; +cvar_t r_maxedges = {"r_maxedges", "0"}; +cvar_t r_numedges = {"r_numedges", "0"}; +cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; +cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; + +extern cvar_t scr_fov; + +void CreatePassages (void); +void SetVisibilityByPassages (void); + +/* +================== +R_InitTextures +================== +*/ +void R_InitTextures (void) +{ + int x,y, m; + byte *dest; + +// create a simple checkerboard texture for the default + r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); + + r_notexture_mip->width = r_notexture_mip->height = 16; + r_notexture_mip->offsets[0] = sizeof(texture_t); + r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; + r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; + r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; + + for (m=0 ; m<4 ; m++) + { + dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; + for (y=0 ; y< (16>>m) ; y++) + for (x=0 ; x< (16>>m) ; x++) + { + if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) + *dest++ = 0; + else + *dest++ = 0xff; + } + } +} + +/* +=============== +R_Init +=============== +*/ +void R_Init (void) +{ + int dummy; + +// get stack position so we can guess if we are going to overflow + r_stack_start = (byte *)&dummy; + + R_InitTurb (); + + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + + Cvar_RegisterVariable (&r_draworder); + Cvar_RegisterVariable (&r_speeds); + Cvar_RegisterVariable (&r_timegraph); + Cvar_RegisterVariable (&r_graphheight); + Cvar_RegisterVariable (&r_drawflat); + Cvar_RegisterVariable (&r_ambient); + Cvar_RegisterVariable (&r_clearcolor); + Cvar_RegisterVariable (&r_waterwarp); + Cvar_RegisterVariable (&r_fullbright); + Cvar_RegisterVariable (&r_drawentities); + Cvar_RegisterVariable (&r_drawviewmodel); + Cvar_RegisterVariable (&r_aliasstats); + Cvar_RegisterVariable (&r_dspeeds); + Cvar_RegisterVariable (&r_reportsurfout); + Cvar_RegisterVariable (&r_maxsurfs); + Cvar_RegisterVariable (&r_numsurfs); + Cvar_RegisterVariable (&r_reportedgeout); + Cvar_RegisterVariable (&r_maxedges); + Cvar_RegisterVariable (&r_numedges); + Cvar_RegisterVariable (&r_aliastransbase); + Cvar_RegisterVariable (&r_aliastransadj); + + Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); + Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); + + view_clipplanes[0].leftedge = true; + view_clipplanes[1].rightedge = true; + view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = + view_clipplanes[3].leftedge = false; + view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = + view_clipplanes[3].rightedge = false; + + r_refdef.xOrigin = XCENTERING; + r_refdef.yOrigin = YCENTERING; + + R_InitParticles (); + +// TODO: collect 386-specific code in one place +#if id386 + Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, + (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); +#endif // id386 + + D_Init (); +} + +/* +=============== +R_NewMap +=============== +*/ +void R_NewMap (void) +{ + int i; + +// clear out efrags in case the level hasn't been reloaded +// FIXME: is this one short? + for (i=0 ; inumleafs ; i++) + cl.worldmodel->leafs[i].efrags = NULL; + + r_viewleaf = NULL; + R_ClearParticles (); + + r_cnumsurfs = r_maxsurfs.value; + + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; + + if (r_cnumsurfs > NUMSTACKSURFACES) + { + surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + else + { + r_surfsonstack = true; + } + + r_maxedgesseen = 0; + r_maxsurfsseen = 0; + + r_numallocatededges = r_maxedges.value; + + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; + + if (r_numallocatededges <= NUMSTACKEDGES) + { + auxedges = NULL; + } + else + { + auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), + "edges"); + } + + r_dowarpold = false; + r_viewchanged = false; +#ifdef PASSAGES +CreatePassages (); +#endif +} + + +/* +=============== +R_SetVrect +=============== +*/ +void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) +{ + int h; + float size; + + size = scr_viewsize.value > 100 ? 100 : scr_viewsize.value; + if (cl.intermission) + { + size = 100; + lineadj = 0; + } + size /= 100; + + h = pvrectin->height - lineadj; + pvrect->width = pvrectin->width * size; + if (pvrect->width < 96) + { + size = 96.0 / pvrectin->width; + pvrect->width = 96; // min for icons + } + pvrect->width &= ~7; + pvrect->height = pvrectin->height * size; + if (pvrect->height > pvrectin->height - lineadj) + pvrect->height = pvrectin->height - lineadj; + + pvrect->height &= ~1; + + pvrect->x = (pvrectin->width - pvrect->width)/2; + pvrect->y = (h - pvrect->height)/2; + + { + if (lcd_x.value) + { + pvrect->y >>= 1; + pvrect->height >>= 1; + } + } +} + + +/* +=============== +R_ViewChanged + +Called every time the vid structure or r_refdef changes. +Guaranteed to be called before the first refresh +=============== +*/ +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) +{ + int i; + float res_scale; + + r_viewchanged = true; + + R_SetVrect (pvrect, &r_refdef.vrect, lineadj); + + r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); + r_refdef.fvrectx = (float)r_refdef.vrect.x; + r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; + r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; + r_refdef.fvrecty = (float)r_refdef.vrect.y; + r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; + r_refdef.fvrectright = (float)r_refdef.vrectright; + r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; + r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; + r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; + + r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); + r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); + r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); + r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); + r_refdef.aliasvrectright = r_refdef.aliasvrect.x + + r_refdef.aliasvrect.width; + r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + + r_refdef.aliasvrect.height; + + pixelAspect = aspect; + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + + screenAspect = r_refdef.vrect.width*pixelAspect / + r_refdef.vrect.height; +// 320*200 1.0 pixelAspect = 1.6 screenAspect +// 320*240 1.0 pixelAspect = 1.3333 screenAspect +// proper 320*200 pixelAspect = 0.8333333 + + verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; + +// values for perspective projection +// if math were exact, the values would range from 0.5 to to range+0.5 +// hopefully they wll be in the 0.000001 to range+.999999 and truncate +// the polygon rasterization will never render in the first row or column +// but will definately render in the [range] row and column, so adjust the +// buffer origin to get an exact edge to edge fill + xcenter = ((float)r_refdef.vrect.width * XCENTERING) + + r_refdef.vrect.x - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float)r_refdef.vrect.height * YCENTERING) + + r_refdef.vrect.y - 0.5; + aliasycenter = ycenter * r_aliasuvscale; + + xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; + aliasxscale = xscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; + yscale = xscale * pixelAspect; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink*pixelAspect; + +// left side clip + screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + +// right side clip + screenedge[1].normal[0] = + 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + +// top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + +// bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; + + for (i=0 ; i<4 ; i++) + VectorNormalize (screenedge[i].normal); + + res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / + (320.0 * 152.0)) * + (2.0 / r_refdef.horizontalFieldOfView); + r_aliastransition = r_aliastransbase.value * res_scale; + r_resfudge = r_aliastransadj.value * res_scale; + + if (scr_fov.value <= 90.0) + r_fov_greater_than_90 = false; + else + r_fov_greater_than_90 = true; + +// TODO: collect 386-specific code in one place +#if id386 + if (r_pixbytes == 1) + { + Sys_MakeCodeWriteable ((long)R_Surf8Start, + (long)R_Surf8End - (long)R_Surf8Start); + colormap = vid.colormap; + R_Surf8Patch (); + } + else + { + Sys_MakeCodeWriteable ((long)R_Surf16Start, + (long)R_Surf16End - (long)R_Surf16Start); + colormap = vid.colormap16; + R_Surf16Patch (); + } +#endif // id386 + + D_ViewChanged (); +} + + +/* +=============== +R_MarkLeaves +=============== +*/ +void R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewleaf == r_viewleaf) + return; + + r_visframecount++; + r_oldviewleaf = r_viewleaf; + + vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + + for (i=0 ; inumleafs ; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *)&cl.worldmodel->leafs[i+1]; + do + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i, j; + int lnum; + alight_t lighting; +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + vec3_t dist; + float add; + + if (!r_drawentities.value) + return; + + for (i=0 ; imodel->type) + { + case mod_sprite: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + R_DrawSprite (); + break; + + case mod_alias: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + if (R_AliasCheckBBox ()) + { + j = R_LightPoint (currententity->origin); + + lighting.ambientlight = j; + lighting.shadelight = j; + + lighting.plightvec = lightvec; + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + + if (add > 0) + lighting.ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting.ambientlight > 128) + lighting.ambientlight = 128; + if (lighting.ambientlight + lighting.shadelight > 192) + lighting.shadelight = 192 - lighting.ambientlight; + + R_AliasDrawModel (&lighting); + } + + break; + + default: + break; + } + } +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + + if (!r_drawviewmodel.value || r_fov_greater_than_90) + return; + + if (cl.items & IT_INVISIBILITY) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + VectorCopy (vup, viewlightvec); + VectorInverse (viewlightvec); + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // allways give some light on gun + r_viewlighting.ambientlight = j; + r_viewlighting.shadelight = j; + +// add dynamic lights + for (lnum=0 ; lnumradius) + continue; + if (!dl->radius) + continue; + if (dl->die < cl.time) + continue; + + VectorSubtract (currententity->origin, dl->origin, dist); + add = dl->radius - Length(dist); + if (add > 0) + r_viewlighting.ambientlight += add; + } + +// clamp lighting so it doesn't overbright as much + if (r_viewlighting.ambientlight > 128) + r_viewlighting.ambientlight = 128; + if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) + r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; + + r_viewlighting.plightvec = lightvec; + +#ifdef QUAKE2 + cl.light_level = r_viewlighting.ambientlight; +#endif + + R_AliasDrawModel (&r_viewlighting); +} + + +/* +============= +R_BmodelCheckBBox +============= +*/ +int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) +{ + int i, *pindex, clipflags; + vec3_t acceptpt, rejectpt; + double d; + + clipflags = 0; + + if (currententity->angles[0] || currententity->angles[1] + || currententity->angles[2]) + { + for (i=0 ; i<4 ; i++) + { + d = DotProduct (currententity->origin, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= -clmodel->radius) + return BMODEL_FULLY_CLIPPED; + + if (d <= clmodel->radius) + clipflags |= (1<model->type) + { + case mod_brush: + + clmodel = currententity->model; + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + for (j=0 ; j<3 ; j++) + { + minmaxs[j] = currententity->origin[j] + + clmodel->mins[j]; + minmaxs[3+j] = currententity->origin[j] + + clmodel->maxs[j]; + } + + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + + if (clipflags != BMODEL_FULLY_CLIPPED) + { + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + // FIXME: is this needed? + VectorCopy (modelorg, r_worldmodelorg); + + r_pcurrentvertbase = clmodel->vertexes; + + // FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); + } + } + + // if the driver wants polygons, deliver those. Z-buffering is on + // at this point, so no clipping to the world tree is needed, just + // frustum clipping + if (r_drawpolys | r_drawculledpolys) + { + R_ZDrawSubmodelPolys (clmodel); + } + else + { + r_pefragtopnode = NULL; + + for (j=0 ; j<3 ; j++) + { + r_emins[j] = minmaxs[j]; + r_emaxs[j] = minmaxs[3+j]; + } + + R_SplitEntityOnNode2 (cl.worldmodel->nodes); + + if (r_pefragtopnode) + { + currententity->topnode = r_pefragtopnode; + + if (r_pefragtopnode->contents >= 0) + { + // not a leaf; has to be clipped to the world BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (clmodel); + } + else + { + // falls entirely in one leaf, so we just put all the + // edges in the edge list and let 1/z sorting handle + // drawing order + R_DrawSubmodelPolygons (clmodel, clipflags); + } + + currententity->topnode = NULL; + } + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + } + + break; + + default: + break; + } + } + + insubmodel = false; +} + + +/* +================ +R_EdgeDrawing +================ +*/ +void R_EdgeDrawing (void) +{ + edge_t ledges[NUMSTACKEDGES + + ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; + + if (auxedges) + { + r_edges = auxedges; + } + else + { + r_edges = (edge_t *) + (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) + { + surfaces = (surf_t *) + (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + + R_BeginEdgeFrame (); + + if (r_dspeeds.value) + { + rw_time1 = Sys_FloatTime (); + } + + R_RenderWorld (); + + if (r_drawculledpolys) + R_ScanEdges (); + +// only the world can be drawn back to front with no z reads or compares, just +// z writes, so have the driver turn z compares on now + D_TurnZOn (); + + if (r_dspeeds.value) + { + rw_time2 = Sys_FloatTime (); + db_time1 = rw_time2; + } + + R_DrawBEntitiesOnList (); + + if (r_dspeeds.value) + { + db_time2 = Sys_FloatTime (); + se_time1 = db_time2; + } + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (!(r_drawpolys | r_drawculledpolys)) + R_ScanEdges (); +} + + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView_ (void) +{ + byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; + + r_warpbuffer = warpbuffer; + + if (r_timegraph.value || r_speeds.value || r_dspeeds.value) + r_time1 = Sys_FloatTime (); + + R_SetupFrame (); + +#ifdef PASSAGES +SetVisibilityByPassages (); +#else + R_MarkLeaves (); // done here so we know if we're in water +#endif + +// make FDIV fast. This reduces timing precision after we've been running for a +// while, so we don't do it globally. This also sets chop mode, and we do it +// here so that setup stuff like the refresh area calculations match what's +// done in screen.c + Sys_LowFPPrecision (); + + if (!cl_entities[0].model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + R_EdgeDrawing (); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (r_dspeeds.value) + { + se_time2 = Sys_FloatTime (); + de_time1 = se_time2; + } + + R_DrawEntitiesOnList (); + + if (r_dspeeds.value) + { + de_time2 = Sys_FloatTime (); + dv_time1 = de_time2; + } + + R_DrawViewModel (); + + if (r_dspeeds.value) + { + dv_time2 = Sys_FloatTime (); + dp_time1 = Sys_FloatTime (); + } + + R_DrawParticles (); + + if (r_dspeeds.value) + dp_time2 = Sys_FloatTime (); + + if (r_dowarp) + D_WarpScreen (); + + V_SetContentsColor (r_viewleaf->contents); + + if (r_timegraph.value) + R_TimeGraph (); + + if (r_aliasstats.value) + R_PrintAliasStats (); + + if (r_speeds.value) + R_PrintTimes (); + + if (r_dspeeds.value) + R_PrintDSpeeds (); + + if (r_reportsurfout.value && r_outofsurfaces) + Con_Printf ("Short %d surfaces\n", r_outofsurfaces); + + if (r_reportedgeout.value && r_outofedges) + Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); + +// back to high floating-point precision + Sys_HighFPPrecision (); +} + +void R_RenderView (void) +{ + int dummy; + int delta; + + delta = (byte *)&dummy - r_stack_start; + if (delta < -10000 || delta > 10000) + Sys_Error ("R_RenderView: called without enough stack"); + + if ( Hunk_LowMark() & 3 ) + Sys_Error ("Hunk is missaligned"); + + if ( (long)(&dummy) & 3 ) + Sys_Error ("Stack is missaligned"); + + if ( (long)(&r_warpbuffer) & 3 ) + Sys_Error ("Globals are missaligned"); + + R_RenderView_ (); +} + +/* +================ +R_InitTurb +================ +*/ +void R_InitTurb (void) +{ + int i; + + for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++) + { + sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; + intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 + } +} + diff --git a/WinQuake/r_misc.c b/WinQuake/r_misc.c index c0aa7e9..a19336f 100644 --- a/WinQuake/r_misc.c +++ b/WinQuake/r_misc.c @@ -1,523 +1,523 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_misc.c - -#include "quakedef.h" -#include "r_local.h" - - -/* -=============== -R_CheckVariables -=============== -*/ -void R_CheckVariables (void) -{ - static float oldbright; - - if (r_fullbright.value != oldbright) - { - oldbright = r_fullbright.value; - D_FlushCaches (); // so all lighting changes - } -} - - -/* -============ -Show - -Debugging use -============ -*/ -void Show (void) -{ - vrect_t vr; - - vr.x = vr.y = 0; - vr.width = vid.width; - vr.height = vid.height; - vr.pnext = NULL; - VID_Update (&vr); -} - - -/* -==================== -R_TimeRefresh_f - -For program optimization -==================== -*/ -void R_TimeRefresh_f (void) -{ - int i; - float start, stop, time; - int startangle; - vrect_t vr; - - startangle = r_refdef.viewangles[1]; - - start = Sys_FloatTime (); - for (i=0 ; i<128 ; i++) - { - r_refdef.viewangles[1] = i/128.0*360.0; - - VID_LockBuffer (); - - R_RenderView (); - - VID_UnlockBuffer (); - - vr.x = r_refdef.vrect.x; - vr.y = r_refdef.vrect.y; - vr.width = r_refdef.vrect.width; - vr.height = r_refdef.vrect.height; - vr.pnext = NULL; - VID_Update (&vr); - } - stop = Sys_FloatTime (); - time = stop-start; - Con_Printf ("%f seconds (%f fps)\n", time, 128/time); - - r_refdef.viewangles[1] = startangle; -} - - -/* -================ -R_LineGraph - -Only called by R_DisplayTime -================ -*/ -void R_LineGraph (int x, int y, int h) -{ - int i; - byte *dest; - int s; - -// FIXME: should be disabled on no-buffer adapters, or should be in the driver - - x += r_refdef.vrect.x; - y += r_refdef.vrect.y; - - dest = vid.buffer + vid.rowbytes*y + x; - - s = r_graphheight.value; - - if (h>s) - h = s; - - for (i=0 ; inormal); - *dist = p->dist - d; -// TODO: when we have rotating entities, this will need to use the view matrix - TransformVector (p->normal, normal); -} - - -/* -=============== -R_SetUpFrustumIndexes -=============== -*/ -void R_SetUpFrustumIndexes (void) -{ - int i, j, *pindex; - - pindex = r_frustum_indexes; - - for (i=0 ; i<4 ; i++) - { - for (j=0 ; j<3 ; j++) - { - if (view_clipplanes[i].normal[j] < 0) - { - pindex[j] = j; - pindex[j+3] = j+3; - } - else - { - pindex[j] = j+3; - pindex[j+3] = j; - } - } - - // FIXME: do just once at start - pfrustum_indexes[i] = pindex; - pindex += 6; - } -} - - -/* -=============== -R_SetupFrame -=============== -*/ -void R_SetupFrame (void) -{ - int edgecount; - vrect_t vrect; - float w, h; - -// don't allow cheats in multiplayer - if (cl.maxclients > 1) - { - Cvar_Set ("r_draworder", "0"); - Cvar_Set ("r_fullbright", "0"); - Cvar_Set ("r_ambient", "0"); - Cvar_Set ("r_drawflat", "0"); - } - - if (r_numsurfs.value) - { - if ((surface_p - surfaces) > r_maxsurfsseen) - r_maxsurfsseen = surface_p - surfaces; - - Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces, - surf_max - surfaces, r_maxsurfsseen); - } - - if (r_numedges.value) - { - edgecount = edge_p - r_edges; - - if (edgecount > r_maxedgesseen) - r_maxedgesseen = edgecount; - - Con_Printf ("Used %d of %d edges; %d max\n", edgecount, - r_numallocatededges, r_maxedgesseen); - } - - r_refdef.ambientlight = r_ambient.value; - - if (r_refdef.ambientlight < 0) - r_refdef.ambientlight = 0; - - if (!sv.active) - r_draworder.value = 0; // don't let cheaters look behind walls - - R_CheckVariables (); - - R_AnimateLight (); - - r_framecount++; - - numbtofpolys = 0; - -// debugging -#if 0 -r_refdef.vieworg[0]= 80; -r_refdef.vieworg[1]= 64; -r_refdef.vieworg[2]= 40; -r_refdef.viewangles[0]= 0; -r_refdef.viewangles[1]= 46.763641357; -r_refdef.viewangles[2]= 0; -#endif - -// build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, modelorg); - VectorCopy (r_refdef.vieworg, r_origin); - - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - -// current viewleaf - r_oldviewleaf = r_viewleaf; - r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); - - r_dowarpold = r_dowarp; - r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER); - - if ((r_dowarp != r_dowarpold) || r_viewchanged || lcd_x.value) - { - if (r_dowarp) - { - if ((vid.width <= vid.maxwarpwidth) && - (vid.height <= vid.maxwarpheight)) - { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_ViewChanged (&vrect, sb_lines, vid.aspect); - } - else - { - w = vid.width; - h = vid.height; - - if (w > vid.maxwarpwidth) - { - h *= (float)vid.maxwarpwidth / w; - w = vid.maxwarpwidth; - } - - if (h > vid.maxwarpheight) - { - h = vid.maxwarpheight; - w *= (float)vid.maxwarpheight / h; - } - - vrect.x = 0; - vrect.y = 0; - vrect.width = (int)w; - vrect.height = (int)h; - - R_ViewChanged (&vrect, - (int)((float)sb_lines * (h/(float)vid.height)), - vid.aspect * (h / w) * - ((float)vid.width / (float)vid.height)); - } - } - else - { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_ViewChanged (&vrect, sb_lines, vid.aspect); - } - - r_viewchanged = false; - } - -// start off with just the four screen edge clip planes - R_TransformFrustum (); - -// save base values - VectorCopy (vpn, base_vpn); - VectorCopy (vright, base_vright); - VectorCopy (vup, base_vup); - VectorCopy (modelorg, base_modelorg); - - R_SetSkyFrame (); - - R_SetUpFrustumIndexes (); - - r_cache_thrash = false; - -// clear frame counts - c_faceclip = 0; - d_spanpixcount = 0; - r_polycount = 0; - r_drawnpolycount = 0; - r_wholepolycount = 0; - r_amodels_drawn = 0; - r_outofsurfaces = 0; - r_outofedges = 0; - - D_SetupFrame (); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_misc.c + +#include "quakedef.h" +#include "r_local.h" + + +/* +=============== +R_CheckVariables +=============== +*/ +void R_CheckVariables (void) +{ + static float oldbright; + + if (r_fullbright.value != oldbright) + { + oldbright = r_fullbright.value; + D_FlushCaches (); // so all lighting changes + } +} + + +/* +============ +Show + +Debugging use +============ +*/ +void Show (void) +{ + vrect_t vr; + + vr.x = vr.y = 0; + vr.width = vid.width; + vr.height = vid.height; + vr.pnext = NULL; + VID_Update (&vr); +} + + +/* +==================== +R_TimeRefresh_f + +For program optimization +==================== +*/ +void R_TimeRefresh_f (void) +{ + int i; + float start, stop, time; + int startangle; + vrect_t vr; + + startangle = r_refdef.viewangles[1]; + + start = Sys_FloatTime (); + for (i=0 ; i<128 ; i++) + { + r_refdef.viewangles[1] = i/128.0*360.0; + + VID_LockBuffer (); + + R_RenderView (); + + VID_UnlockBuffer (); + + vr.x = r_refdef.vrect.x; + vr.y = r_refdef.vrect.y; + vr.width = r_refdef.vrect.width; + vr.height = r_refdef.vrect.height; + vr.pnext = NULL; + VID_Update (&vr); + } + stop = Sys_FloatTime (); + time = stop-start; + Con_Printf ("%f seconds (%f fps)\n", time, 128/time); + + r_refdef.viewangles[1] = startangle; +} + + +/* +================ +R_LineGraph + +Only called by R_DisplayTime +================ +*/ +void R_LineGraph (int x, int y, int h) +{ + int i; + byte *dest; + int s; + +// FIXME: should be disabled on no-buffer adapters, or should be in the driver + + x += r_refdef.vrect.x; + y += r_refdef.vrect.y; + + dest = vid.buffer + vid.rowbytes*y + x; + + s = r_graphheight.value; + + if (h>s) + h = s; + + for (i=0 ; inormal); + *dist = p->dist - d; +// TODO: when we have rotating entities, this will need to use the view matrix + TransformVector (p->normal, normal); +} + + +/* +=============== +R_SetUpFrustumIndexes +=============== +*/ +void R_SetUpFrustumIndexes (void) +{ + int i, j, *pindex; + + pindex = r_frustum_indexes; + + for (i=0 ; i<4 ; i++) + { + for (j=0 ; j<3 ; j++) + { + if (view_clipplanes[i].normal[j] < 0) + { + pindex[j] = j; + pindex[j+3] = j+3; + } + else + { + pindex[j] = j+3; + pindex[j+3] = j; + } + } + + // FIXME: do just once at start + pfrustum_indexes[i] = pindex; + pindex += 6; + } +} + + +/* +=============== +R_SetupFrame +=============== +*/ +void R_SetupFrame (void) +{ + int edgecount; + vrect_t vrect; + float w, h; + +// don't allow cheats in multiplayer + if (cl.maxclients > 1) + { + Cvar_Set ("r_draworder", "0"); + Cvar_Set ("r_fullbright", "0"); + Cvar_Set ("r_ambient", "0"); + Cvar_Set ("r_drawflat", "0"); + } + + if (r_numsurfs.value) + { + if ((surface_p - surfaces) > r_maxsurfsseen) + r_maxsurfsseen = surface_p - surfaces; + + Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces, + surf_max - surfaces, r_maxsurfsseen); + } + + if (r_numedges.value) + { + edgecount = edge_p - r_edges; + + if (edgecount > r_maxedgesseen) + r_maxedgesseen = edgecount; + + Con_Printf ("Used %d of %d edges; %d max\n", edgecount, + r_numallocatededges, r_maxedgesseen); + } + + r_refdef.ambientlight = r_ambient.value; + + if (r_refdef.ambientlight < 0) + r_refdef.ambientlight = 0; + + if (!sv.active) + r_draworder.value = 0; // don't let cheaters look behind walls + + R_CheckVariables (); + + R_AnimateLight (); + + r_framecount++; + + numbtofpolys = 0; + +// debugging +#if 0 +r_refdef.vieworg[0]= 80; +r_refdef.vieworg[1]= 64; +r_refdef.vieworg[2]= 40; +r_refdef.viewangles[0]= 0; +r_refdef.viewangles[1]= 46.763641357; +r_refdef.viewangles[2]= 0; +#endif + +// build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, modelorg); + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + +// current viewleaf + r_oldviewleaf = r_viewleaf; + r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + + r_dowarpold = r_dowarp; + r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER); + + if ((r_dowarp != r_dowarpold) || r_viewchanged || lcd_x.value) + { + if (r_dowarp) + { + if ((vid.width <= vid.maxwarpwidth) && + (vid.height <= vid.maxwarpheight)) + { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_ViewChanged (&vrect, sb_lines, vid.aspect); + } + else + { + w = vid.width; + h = vid.height; + + if (w > vid.maxwarpwidth) + { + h *= (float)vid.maxwarpwidth / w; + w = vid.maxwarpwidth; + } + + if (h > vid.maxwarpheight) + { + h = vid.maxwarpheight; + w *= (float)vid.maxwarpheight / h; + } + + vrect.x = 0; + vrect.y = 0; + vrect.width = (int)w; + vrect.height = (int)h; + + R_ViewChanged (&vrect, + (int)((float)sb_lines * (h/(float)vid.height)), + vid.aspect * (h / w) * + ((float)vid.width / (float)vid.height)); + } + } + else + { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_ViewChanged (&vrect, sb_lines, vid.aspect); + } + + r_viewchanged = false; + } + +// start off with just the four screen edge clip planes + R_TransformFrustum (); + +// save base values + VectorCopy (vpn, base_vpn); + VectorCopy (vright, base_vright); + VectorCopy (vup, base_vup); + VectorCopy (modelorg, base_modelorg); + + R_SetSkyFrame (); + + R_SetUpFrustumIndexes (); + + r_cache_thrash = false; + +// clear frame counts + c_faceclip = 0; + d_spanpixcount = 0; + r_polycount = 0; + r_drawnpolycount = 0; + r_wholepolycount = 0; + r_amodels_drawn = 0; + r_outofsurfaces = 0; + r_outofedges = 0; + + D_SetupFrame (); +} + diff --git a/WinQuake/r_part.c b/WinQuake/r_part.c index 3db22ab..5586440 100644 --- a/WinQuake/r_part.c +++ b/WinQuake/r_part.c @@ -1,800 +1,800 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" -#include "r_local.h" - -#define MAX_PARTICLES 2048 // default max # of particles at one - // time -#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's - // on the command line - -int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; -int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; -int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; - -particle_t *active_particles, *free_particles; - -particle_t *particles; -int r_numparticles; - -vec3_t r_pright, r_pup, r_ppn; - - -/* -=============== -R_InitParticles -=============== -*/ -void R_InitParticles (void) -{ - int i; - - i = COM_CheckParm ("-particles"); - - if (i) - { - r_numparticles = (int)(Q_atoi(com_argv[i+1])); - if (r_numparticles < ABSOLUTE_MIN_PARTICLES) - r_numparticles = ABSOLUTE_MIN_PARTICLES; - } - else - { - r_numparticles = MAX_PARTICLES; - } - - particles = (particle_t *) - Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); -} - -#ifdef QUAKE2 -void R_DarkFieldParticles (entity_t *ent) -{ - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - vec3_t org; - - org[0] = ent->origin[0]; - org[1] = ent->origin[1]; - org[2] = ent->origin[2]; - for (i=-16 ; i<16 ; i+=8) - for (j=-16 ; j<16 ; j+=8) - for (k=0 ; k<32 ; k+=8) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 0.2 + (rand()&7) * 0.02; - p->color = 150 + rand()%6; - p->type = pt_slowgrav; - - dir[0] = j*8; - dir[1] = i*8; - dir[2] = k*8; - - p->org[0] = org[0] + i + (rand()&3); - p->org[1] = org[1] + j + (rand()&3); - p->org[2] = org[2] + k + (rand()&3); - - VectorNormalize (dir); - vel = 50 + (rand()&63); - VectorScale (dir, vel, p->vel); - } -} -#endif - - -/* -=============== -R_EntityParticles -=============== -*/ - -#define NUMVERTEXNORMALS 162 -extern float r_avertexnormals[NUMVERTEXNORMALS][3]; -vec3_t avelocities[NUMVERTEXNORMALS]; -float beamlength = 16; -vec3_t avelocity = {23, 7, 3}; -float partstep = 0.01; -float timescale = 0.01; - -void R_EntityParticles (entity_t *ent) -{ - int count; - int i; - particle_t *p; - float angle; - float sr, sp, sy, cr, cp, cy; - vec3_t forward; - float dist; - - dist = 64; - count = 50; - -if (!avelocities[0][0]) -{ -for (i=0 ; inext; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 0.01; - p->color = 0x6f; - p->type = pt_explode; - - p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength; - p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength; - p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength; - } -} - - -/* -=============== -R_ClearParticles -=============== -*/ -void R_ClearParticles (void) -{ - int i; - - free_particles = &particles[0]; - active_particles = NULL; - - for (i=0 ;inext; - p->next = active_particles; - active_particles = p; - - p->die = 99999; - p->color = (-c)&15; - p->type = pt_static; - VectorCopy (vec3_origin, p->vel); - VectorCopy (org, p->org); - } - - fclose (f); - Con_Printf ("%i points read\n", c); -} - -/* -=============== -R_ParseParticleEffect - -Parse an effect out of the server message -=============== -*/ -void R_ParseParticleEffect (void) -{ - vec3_t org, dir; - int i, count, msgcount, color; - - for (i=0 ; i<3 ; i++) - org[i] = MSG_ReadCoord (); - for (i=0 ; i<3 ; i++) - dir[i] = MSG_ReadChar () * (1.0/16); - msgcount = MSG_ReadByte (); - color = MSG_ReadByte (); - -if (msgcount == 255) - count = 1024; -else - count = msgcount; - - R_RunParticleEffect (org, dir, color, count); -} - -/* -=============== -R_ParticleExplosion - -=============== -*/ -void R_ParticleExplosion (vec3_t org) -{ - int i, j; - particle_t *p; - - for (i=0 ; i<1024 ; i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 5; - p->color = ramp1[0]; - p->ramp = rand()&3; - if (i & 1) - { - p->type = pt_explode; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - else - { - p->type = pt_explode2; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - } -} - -/* -=============== -R_ParticleExplosion2 - -=============== -*/ -void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) -{ - int i, j; - particle_t *p; - int colorMod = 0; - - for (i=0; i<512; i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 0.3; - p->color = colorStart + (colorMod % colorLength); - colorMod++; - - p->type = pt_blob; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } -} - -/* -=============== -R_BlobExplosion - -=============== -*/ -void R_BlobExplosion (vec3_t org) -{ - int i, j; - particle_t *p; - - for (i=0 ; i<1024 ; i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 1 + (rand()&8)*0.05; - - if (i & 1) - { - p->type = pt_blob; - p->color = 66 + rand()%6; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - else - { - p->type = pt_blob2; - p->color = 150 + rand()%6; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - } -} - -/* -=============== -R_RunParticleEffect - -=============== -*/ -void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) -{ - int i, j; - particle_t *p; - - for (i=0 ; inext; - p->next = active_particles; - active_particles = p; - - if (count == 1024) - { // rocket explosion - p->die = cl.time + 5; - p->color = ramp1[0]; - p->ramp = rand()&3; - if (i & 1) - { - p->type = pt_explode; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - else - { - p->type = pt_explode2; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()%32)-16); - p->vel[j] = (rand()%512)-256; - } - } - } - else - { - p->die = cl.time + 0.1*(rand()%5); - p->color = (color&~7) + (rand()&7); - p->type = pt_slowgrav; - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((rand()&15)-8); - p->vel[j] = dir[j]*15;// + (rand()%300)-150; - } - } - } -} - - -/* -=============== -R_LavaSplash - -=============== -*/ -void R_LavaSplash (vec3_t org) -{ - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - - for (i=-16 ; i<16 ; i++) - for (j=-16 ; j<16 ; j++) - for (k=0 ; k<1 ; k++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 2 + (rand()&31) * 0.02; - p->color = 224 + (rand()&7); - p->type = pt_slowgrav; - - dir[0] = j*8 + (rand()&7); - dir[1] = i*8 + (rand()&7); - dir[2] = 256; - - p->org[0] = org[0] + dir[0]; - p->org[1] = org[1] + dir[1]; - p->org[2] = org[2] + (rand()&63); - - VectorNormalize (dir); - vel = 50 + (rand()&63); - VectorScale (dir, vel, p->vel); - } -} - -/* -=============== -R_TeleportSplash - -=============== -*/ -void R_TeleportSplash (vec3_t org) -{ - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - - for (i=-16 ; i<16 ; i+=4) - for (j=-16 ; j<16 ; j+=4) - for (k=-24 ; k<32 ; k+=4) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = cl.time + 0.2 + (rand()&7) * 0.02; - p->color = 7 + (rand()&7); - p->type = pt_slowgrav; - - dir[0] = j*8; - dir[1] = i*8; - dir[2] = k*8; - - p->org[0] = org[0] + i + (rand()&3); - p->org[1] = org[1] + j + (rand()&3); - p->org[2] = org[2] + k + (rand()&3); - - VectorNormalize (dir); - vel = 50 + (rand()&63); - VectorScale (dir, vel, p->vel); - } -} - -void R_RocketTrail (vec3_t start, vec3_t end, int type) -{ - vec3_t vec; - float len; - int j; - particle_t *p; - int dec; - static int tracercount; - - VectorSubtract (end, start, vec); - len = VectorNormalize (vec); - if (type < 128) - dec = 3; - else - { - dec = 1; - type -= 128; - } - - while (len > 0) - { - len -= dec; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorCopy (vec3_origin, p->vel); - p->die = cl.time + 2; - - switch (type) - { - case 0: // rocket trail - p->ramp = (rand()&3); - p->color = ramp3[(int)p->ramp]; - p->type = pt_fire; - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()%6)-3); - break; - - case 1: // smoke smoke - p->ramp = (rand()&3) + 2; - p->color = ramp3[(int)p->ramp]; - p->type = pt_fire; - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()%6)-3); - break; - - case 2: // blood - p->type = pt_grav; - p->color = 67 + (rand()&3); - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()%6)-3); - break; - - case 3: - case 5: // tracer - p->die = cl.time + 0.5; - p->type = pt_static; - if (type == 3) - p->color = 52 + ((tracercount&4)<<1); - else - p->color = 230 + ((tracercount&4)<<1); - - tracercount++; - - VectorCopy (start, p->org); - if (tracercount & 1) - { - p->vel[0] = 30*vec[1]; - p->vel[1] = 30*-vec[0]; - } - else - { - p->vel[0] = 30*-vec[1]; - p->vel[1] = 30*vec[0]; - } - break; - - case 4: // slight blood - p->type = pt_grav; - p->color = 67 + (rand()&3); - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()%6)-3); - len -= 3; - break; - - case 6: // voor trail - p->color = 9*16 + 8 + (rand()&3); - p->type = pt_static; - p->die = cl.time + 0.3; - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()&15)-8); - break; - } - - - VectorAdd (start, vec, start); - } -} - - -/* -=============== -R_DrawParticles -=============== -*/ -extern cvar_t sv_gravity; - -void R_DrawParticles (void) -{ - particle_t *p, *kill; - float grav; - int i; - float time2, time3; - float time1; - float dvel; - float frametime; - -#ifdef GLQUAKE - vec3_t up, right; - float scale; - - GL_Bind(particletexture); - glEnable (GL_BLEND); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBegin (GL_TRIANGLES); - - VectorScale (vup, 1.5, up); - VectorScale (vright, 1.5, right); -#else - D_StartParticles (); - - VectorScale (vright, xscaleshrink, r_pright); - VectorScale (vup, yscaleshrink, r_pup); - VectorCopy (vpn, r_ppn); -#endif - frametime = cl.time - cl.oldtime; - time3 = frametime * 15; - time2 = frametime * 10; // 15; - time1 = frametime * 5; - grav = frametime * sv_gravity.value * 0.05; - dvel = 4*frametime; - - for ( ;; ) - { - kill = active_particles; - if (kill && kill->die < cl.time) - { - active_particles = kill->next; - kill->next = free_particles; - free_particles = kill; - continue; - } - break; - } - - for (p=active_particles ; p ; p=p->next) - { - for ( ;; ) - { - kill = p->next; - if (kill && kill->die < cl.time) - { - p->next = kill->next; - kill->next = free_particles; - free_particles = kill; - continue; - } - break; - } - -#ifdef GLQUAKE - // hack a scale up to keep particles from disapearing - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - if (scale < 20) - scale = 1; - else - scale = 1 + scale * 0.004; - glColor3ubv ((byte *)&d_8to24table[(int)p->color]); - glTexCoord2f (0,0); - glVertex3fv (p->org); - glTexCoord2f (1,0); - glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); - glTexCoord2f (0,1); - glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); -#else - D_DrawParticle (p); -#endif - p->org[0] += p->vel[0]*frametime; - p->org[1] += p->vel[1]*frametime; - p->org[2] += p->vel[2]*frametime; - - switch (p->type) - { - case pt_static: - break; - case pt_fire: - p->ramp += time1; - if (p->ramp >= 6) - p->die = -1; - else - p->color = ramp3[(int)p->ramp]; - p->vel[2] += grav; - break; - - case pt_explode: - p->ramp += time2; - if (p->ramp >=8) - p->die = -1; - else - p->color = ramp1[(int)p->ramp]; - for (i=0 ; i<3 ; i++) - p->vel[i] += p->vel[i]*dvel; - p->vel[2] -= grav; - break; - - case pt_explode2: - p->ramp += time3; - if (p->ramp >=8) - p->die = -1; - else - p->color = ramp2[(int)p->ramp]; - for (i=0 ; i<3 ; i++) - p->vel[i] -= p->vel[i]*frametime; - p->vel[2] -= grav; - break; - - case pt_blob: - for (i=0 ; i<3 ; i++) - p->vel[i] += p->vel[i]*dvel; - p->vel[2] -= grav; - break; - - case pt_blob2: - for (i=0 ; i<2 ; i++) - p->vel[i] -= p->vel[i]*dvel; - p->vel[2] -= grav; - break; - - case pt_grav: -#ifdef QUAKE2 - p->vel[2] -= grav * 20; - break; -#endif - case pt_slowgrav: - p->vel[2] -= grav; - break; - } - } - -#ifdef GLQUAKE - glEnd (); - glDisable (GL_BLEND); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -#else - D_EndParticles (); -#endif -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" +#include "r_local.h" + +#define MAX_PARTICLES 2048 // default max # of particles at one + // time +#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's + // on the command line + +int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; +int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; +int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; + +particle_t *active_particles, *free_particles; + +particle_t *particles; +int r_numparticles; + +vec3_t r_pright, r_pup, r_ppn; + + +/* +=============== +R_InitParticles +=============== +*/ +void R_InitParticles (void) +{ + int i; + + i = COM_CheckParm ("-particles"); + + if (i) + { + r_numparticles = (int)(Q_atoi(com_argv[i+1])); + if (r_numparticles < ABSOLUTE_MIN_PARTICLES) + r_numparticles = ABSOLUTE_MIN_PARTICLES; + } + else + { + r_numparticles = MAX_PARTICLES; + } + + particles = (particle_t *) + Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); +} + +#ifdef QUAKE2 +void R_DarkFieldParticles (entity_t *ent) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + vec3_t org; + + org[0] = ent->origin[0]; + org[1] = ent->origin[1]; + org[2] = ent->origin[2]; + for (i=-16 ; i<16 ; i+=8) + for (j=-16 ; j<16 ; j+=8) + for (k=0 ; k<32 ; k+=8) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.2 + (rand()&7) * 0.02; + p->color = 150 + rand()%6; + p->type = pt_slowgrav; + + dir[0] = j*8; + dir[1] = i*8; + dir[2] = k*8; + + p->org[0] = org[0] + i + (rand()&3); + p->org[1] = org[1] + j + (rand()&3); + p->org[2] = org[2] + k + (rand()&3); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} +#endif + + +/* +=============== +R_EntityParticles +=============== +*/ + +#define NUMVERTEXNORMALS 162 +extern float r_avertexnormals[NUMVERTEXNORMALS][3]; +vec3_t avelocities[NUMVERTEXNORMALS]; +float beamlength = 16; +vec3_t avelocity = {23, 7, 3}; +float partstep = 0.01; +float timescale = 0.01; + +void R_EntityParticles (entity_t *ent) +{ + int count; + int i; + particle_t *p; + float angle; + float sr, sp, sy, cr, cp, cy; + vec3_t forward; + float dist; + + dist = 64; + count = 50; + +if (!avelocities[0][0]) +{ +for (i=0 ; inext; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.01; + p->color = 0x6f; + p->type = pt_explode; + + p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength; + p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength; + p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength; + } +} + + +/* +=============== +R_ClearParticles +=============== +*/ +void R_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + active_particles = NULL; + + for (i=0 ;inext; + p->next = active_particles; + active_particles = p; + + p->die = 99999; + p->color = (-c)&15; + p->type = pt_static; + VectorCopy (vec3_origin, p->vel); + VectorCopy (org, p->org); + } + + fclose (f); + Con_Printf ("%i points read\n", c); +} + +/* +=============== +R_ParseParticleEffect + +Parse an effect out of the server message +=============== +*/ +void R_ParseParticleEffect (void) +{ + vec3_t org, dir; + int i, count, msgcount, color; + + for (i=0 ; i<3 ; i++) + org[i] = MSG_ReadCoord (); + for (i=0 ; i<3 ; i++) + dir[i] = MSG_ReadChar () * (1.0/16); + msgcount = MSG_ReadByte (); + color = MSG_ReadByte (); + +if (msgcount == 255) + count = 1024; +else + count = msgcount; + + R_RunParticleEffect (org, dir, color, count); +} + +/* +=============== +R_ParticleExplosion + +=============== +*/ +void R_ParticleExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand()&3; + if (i & 1) + { + p->type = pt_explode; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_explode2; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_ParticleExplosion2 + +=============== +*/ +void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) +{ + int i, j; + particle_t *p; + int colorMod = 0; + + for (i=0; i<512; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.3; + p->color = colorStart + (colorMod % colorLength); + colorMod++; + + p->type = pt_blob; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } +} + +/* +=============== +R_BlobExplosion + +=============== +*/ +void R_BlobExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 1 + (rand()&8)*0.05; + + if (i & 1) + { + p->type = pt_blob; + p->color = 66 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_blob2; + p->color = 150 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_RunParticleEffect + +=============== +*/ +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + int i, j; + particle_t *p; + + for (i=0 ; inext; + p->next = active_particles; + active_particles = p; + + if (count == 1024) + { // rocket explosion + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand()&3; + if (i & 1) + { + p->type = pt_explode; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_explode2; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } + else + { + p->die = cl.time + 0.1*(rand()%5); + p->color = (color&~7) + (rand()&7); + p->type = pt_slowgrav; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()&15)-8); + p->vel[j] = dir[j]*15;// + (rand()%300)-150; + } + } + } +} + + +/* +=============== +R_LavaSplash + +=============== +*/ +void R_LavaSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i++) + for (j=-16 ; j<16 ; j++) + for (k=0 ; k<1 ; k++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 2 + (rand()&31) * 0.02; + p->color = 224 + (rand()&7); + p->type = pt_slowgrav; + + dir[0] = j*8 + (rand()&7); + dir[1] = i*8 + (rand()&7); + dir[2] = 256; + + p->org[0] = org[0] + dir[0]; + p->org[1] = org[1] + dir[1]; + p->org[2] = org[2] + (rand()&63); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +/* +=============== +R_TeleportSplash + +=============== +*/ +void R_TeleportSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i+=4) + for (j=-16 ; j<16 ; j+=4) + for (k=-24 ; k<32 ; k+=4) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.2 + (rand()&7) * 0.02; + p->color = 7 + (rand()&7); + p->type = pt_slowgrav; + + dir[0] = j*8; + dir[1] = i*8; + dir[2] = k*8; + + p->org[0] = org[0] + i + (rand()&3); + p->org[1] = org[1] + j + (rand()&3); + p->org[2] = org[2] + k + (rand()&3); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +void R_RocketTrail (vec3_t start, vec3_t end, int type) +{ + vec3_t vec; + float len; + int j; + particle_t *p; + int dec; + static int tracercount; + + VectorSubtract (end, start, vec); + len = VectorNormalize (vec); + if (type < 128) + dec = 3; + else + { + dec = 1; + type -= 128; + } + + while (len > 0) + { + len -= dec; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (vec3_origin, p->vel); + p->die = cl.time + 2; + + switch (type) + { + case 0: // rocket trail + p->ramp = (rand()&3); + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 1: // smoke smoke + p->ramp = (rand()&3) + 2; + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 2: // blood + p->type = pt_grav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 3: + case 5: // tracer + p->die = cl.time + 0.5; + p->type = pt_static; + if (type == 3) + p->color = 52 + ((tracercount&4)<<1); + else + p->color = 230 + ((tracercount&4)<<1); + + tracercount++; + + VectorCopy (start, p->org); + if (tracercount & 1) + { + p->vel[0] = 30*vec[1]; + p->vel[1] = 30*-vec[0]; + } + else + { + p->vel[0] = 30*-vec[1]; + p->vel[1] = 30*vec[0]; + } + break; + + case 4: // slight blood + p->type = pt_grav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + len -= 3; + break; + + case 6: // voor trail + p->color = 9*16 + 8 + (rand()&3); + p->type = pt_static; + p->die = cl.time + 0.3; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()&15)-8); + break; + } + + + VectorAdd (start, vec, start); + } +} + + +/* +=============== +R_DrawParticles +=============== +*/ +extern cvar_t sv_gravity; + +void R_DrawParticles (void) +{ + particle_t *p, *kill; + float grav; + int i; + float time2, time3; + float time1; + float dvel; + float frametime; + +#ifdef GLQUAKE + vec3_t up, right; + float scale; + + GL_Bind(particletexture); + glEnable (GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBegin (GL_TRIANGLES); + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); +#else + D_StartParticles (); + + VectorScale (vright, xscaleshrink, r_pright); + VectorScale (vup, yscaleshrink, r_pup); + VectorCopy (vpn, r_ppn); +#endif + frametime = cl.time - cl.oldtime; + time3 = frametime * 15; + time2 = frametime * 10; // 15; + time1 = frametime * 5; + grav = frametime * sv_gravity.value * 0.05; + dvel = 4*frametime; + + for ( ;; ) + { + kill = active_particles; + if (kill && kill->die < cl.time) + { + active_particles = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + for (p=active_particles ; p ; p=p->next) + { + for ( ;; ) + { + kill = p->next; + if (kill && kill->die < cl.time) + { + p->next = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + +#ifdef GLQUAKE + // hack a scale up to keep particles from disapearing + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + if (scale < 20) + scale = 1; + else + scale = 1 + scale * 0.004; + glColor3ubv ((byte *)&d_8to24table[(int)p->color]); + glTexCoord2f (0,0); + glVertex3fv (p->org); + glTexCoord2f (1,0); + glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); + glTexCoord2f (0,1); + glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); +#else + D_DrawParticle (p); +#endif + p->org[0] += p->vel[0]*frametime; + p->org[1] += p->vel[1]*frametime; + p->org[2] += p->vel[2]*frametime; + + switch (p->type) + { + case pt_static: + break; + case pt_fire: + p->ramp += time1; + if (p->ramp >= 6) + p->die = -1; + else + p->color = ramp3[(int)p->ramp]; + p->vel[2] += grav; + break; + + case pt_explode: + p->ramp += time2; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp1[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_explode2: + p->ramp += time3; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp2[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] -= p->vel[i]*frametime; + p->vel[2] -= grav; + break; + + case pt_blob: + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_blob2: + for (i=0 ; i<2 ; i++) + p->vel[i] -= p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_grav: +#ifdef QUAKE2 + p->vel[2] -= grav * 20; + break; +#endif + case pt_slowgrav: + p->vel[2] -= grav; + break; + } + } + +#ifdef GLQUAKE + glEnd (); + glDisable (GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +#else + D_EndParticles (); +#endif +} + diff --git a/WinQuake/r_shared.h b/WinQuake/r_shared.h index f2a6db3..2d22f7d 100644 --- a/WinQuake/r_shared.h +++ b/WinQuake/r_shared.h @@ -1,157 +1,157 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef GLQUAKE -// r_shared.h: general refresh-related stuff shared between the refresh and the -// driver - -// FIXME: clean up and move into d_iface.h - -#ifndef _R_SHARED_H_ -#define _R_SHARED_H_ - -#define MAXVERTS 16 // max points in a surface polygon -#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate - // polygon (while processing) -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -#define MAXHEIGHT 1024 -#define MAXWIDTH 1280 -#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH) - -#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE) - -#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to - // be farther away than anything in - // the scene - -//=================================================================== - -extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); - -extern int cachewidth; -extern pixel_t *cacheblock; -extern int screenwidth; - -extern float pixelAspect; - -extern int r_drawnpolycount; - -extern cvar_t r_clearcolor; - -extern int sintable[SIN_BUFFER_SIZE]; -extern int intsintable[SIN_BUFFER_SIZE]; - -extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; -extern vec3_t vright, base_vright; -extern entity_t *currententity; - -#define NUMSTACKEDGES 2400 -#define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 800 -#define MINSURFACES NUMSTACKSURFACES -#define MAXSPANS 3000 - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct espan_s -{ - int u, v, count; - struct espan_s *pnext; -} espan_t; - -// FIXME: compress, make a union if that will help -// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte -typedef struct surf_s -{ - struct surf_s *next; // active surface stack in r_edge.c - struct surf_s *prev; // used in r_edge.c for active surf stack - struct espan_s *spans; // pointer to linked list of spans to draw - int key; // sorting key (BSP order) - int last_u; // set during tracing - int spanstate; // 0 = not in span - // 1 = in span - // -1 = in inverted span (end before - // start) - int flags; // currentface flags - void *data; // associated data like msurface_t - entity_t *entity; - float nearzi; // nearest 1/z on surface, for mipmapping - qboolean insubmodel; - float d_ziorigin, d_zistepu, d_zistepv; - - int pad[2]; // to 64 bytes -} surf_t; - -extern surf_t *surfaces, *surface_p, *surf_max; - -// surfaces are generated in back to front order by the bsp, so if a surf -// pointer is greater than another one, it should be drawn in front -// surfaces[1] is the background, and is used as the active surface stack. -// surfaces[0] is a dummy, because index 0 is used to indicate no surface -// attached to an edge_t - -//=================================================================== - -extern vec3_t sxformaxis[4]; // s axis transformed into viewspace -extern vec3_t txformaxis[4]; // t axis transformed into viewspac - -extern vec3_t modelorg, base_modelorg; - -extern float xcenter, ycenter; -extern float xscale, yscale; -extern float xscaleinv, yscaleinv; -extern float xscaleshrink, yscaleshrink; - -extern int d_lightstylevalue[256]; // 8.8 frac of base light value - -extern void TransformVector (vec3_t in, vec3_t out); -extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, - fixed8_t endvertu, fixed8_t endvertv); - -extern int r_skymade; -extern void R_MakeSky (void); - -extern int ubasestep, errorterm, erroradjustup, erroradjustdown; - -// flags in finalvert_t.flags -#define ALIAS_LEFT_CLIP 0x0001 -#define ALIAS_TOP_CLIP 0x0002 -#define ALIAS_RIGHT_CLIP 0x0004 -#define ALIAS_BOTTOM_CLIP 0x0008 -#define ALIAS_Z_CLIP 0x0010 -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h; - // must be kept in sync -#define ALIAS_XY_CLIP_MASK 0x000F - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct edge_s -{ - fixed16_t u; - fixed16_t u_step; - struct edge_s *prev, *next; - unsigned short surfs[2]; - struct edge_s *nextremove; - float nearzi; - medge_t *owner; -} edge_t; - -#endif // _R_SHARED_H_ - -#endif // GLQUAKE +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef GLQUAKE +// r_shared.h: general refresh-related stuff shared between the refresh and the +// driver + +// FIXME: clean up and move into d_iface.h + +#ifndef _R_SHARED_H_ +#define _R_SHARED_H_ + +#define MAXVERTS 16 // max points in a surface polygon +#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate + // polygon (while processing) +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +#define MAXHEIGHT 1024 +#define MAXWIDTH 1280 +#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH) + +#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE) + +#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to + // be farther away than anything in + // the scene + +//=================================================================== + +extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); + +extern int cachewidth; +extern pixel_t *cacheblock; +extern int screenwidth; + +extern float pixelAspect; + +extern int r_drawnpolycount; + +extern cvar_t r_clearcolor; + +extern int sintable[SIN_BUFFER_SIZE]; +extern int intsintable[SIN_BUFFER_SIZE]; + +extern vec3_t vup, base_vup; +extern vec3_t vpn, base_vpn; +extern vec3_t vright, base_vright; +extern entity_t *currententity; + +#define NUMSTACKEDGES 2400 +#define MINEDGES NUMSTACKEDGES +#define NUMSTACKSURFACES 800 +#define MINSURFACES NUMSTACKSURFACES +#define MAXSPANS 3000 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct espan_s +{ + int u, v, count; + struct espan_s *pnext; +} espan_t; + +// FIXME: compress, make a union if that will help +// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte +typedef struct surf_s +{ + struct surf_s *next; // active surface stack in r_edge.c + struct surf_s *prev; // used in r_edge.c for active surf stack + struct espan_s *spans; // pointer to linked list of spans to draw + int key; // sorting key (BSP order) + int last_u; // set during tracing + int spanstate; // 0 = not in span + // 1 = in span + // -1 = in inverted span (end before + // start) + int flags; // currentface flags + void *data; // associated data like msurface_t + entity_t *entity; + float nearzi; // nearest 1/z on surface, for mipmapping + qboolean insubmodel; + float d_ziorigin, d_zistepu, d_zistepv; + + int pad[2]; // to 64 bytes +} surf_t; + +extern surf_t *surfaces, *surface_p, *surf_max; + +// surfaces are generated in back to front order by the bsp, so if a surf +// pointer is greater than another one, it should be drawn in front +// surfaces[1] is the background, and is used as the active surface stack. +// surfaces[0] is a dummy, because index 0 is used to indicate no surface +// attached to an edge_t + +//=================================================================== + +extern vec3_t sxformaxis[4]; // s axis transformed into viewspace +extern vec3_t txformaxis[4]; // t axis transformed into viewspac + +extern vec3_t modelorg, base_modelorg; + +extern float xcenter, ycenter; +extern float xscale, yscale; +extern float xscaleinv, yscaleinv; +extern float xscaleshrink, yscaleshrink; + +extern int d_lightstylevalue[256]; // 8.8 frac of base light value + +extern void TransformVector (vec3_t in, vec3_t out); +extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, + fixed8_t endvertu, fixed8_t endvertv); + +extern int r_skymade; +extern void R_MakeSky (void); + +extern int ubasestep, errorterm, erroradjustup, erroradjustdown; + +// flags in finalvert_t.flags +#define ALIAS_LEFT_CLIP 0x0001 +#define ALIAS_TOP_CLIP 0x0002 +#define ALIAS_RIGHT_CLIP 0x0004 +#define ALIAS_BOTTOM_CLIP 0x0008 +#define ALIAS_Z_CLIP 0x0010 +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h; + // must be kept in sync +#define ALIAS_XY_CLIP_MASK 0x000F + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct edge_s +{ + fixed16_t u; + fixed16_t u_step; + struct edge_s *prev, *next; + unsigned short surfs[2]; + struct edge_s *nextremove; + float nearzi; + medge_t *owner; +} edge_t; + +#endif // _R_SHARED_H_ + +#endif // GLQUAKE diff --git a/WinQuake/r_sky.c b/WinQuake/r_sky.c index c8bfffd..91b17d7 100644 --- a/WinQuake/r_sky.c +++ b/WinQuake/r_sky.c @@ -1,280 +1,280 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_sky.c - -#include "quakedef.h" -#include "r_local.h" -#include "d_local.h" - - -int iskyspeed = 8; -int iskyspeed2 = 2; -float skyspeed, skyspeed2; - -float skytime; - -byte *r_skysource; - -int r_skymade; -int r_skydirect; // not used? - - -// TODO: clean up these routines - -byte bottomsky[128*131]; -byte bottommask[128*131]; -byte newsky[128*256]; // newsky and topsky both pack in here, 128 bytes - // of newsky on the left of each scan, 128 bytes - // of topsky on the right, because the low-level - // drawers need 256-byte scan widths - - -/* -============= -R_InitSky - -A sky texture is 256*128, with the right side being a masked overlay -============== -*/ -void R_InitSky (texture_t *mt) -{ - int i, j; - byte *src; - - src = (byte *)mt + mt->offsets[0]; - - for (i=0 ; i<128 ; i++) - { - for (j=0 ; j<128 ; j++) - { - newsky[(i*256) + j + 128] = src[i*256 + j + 128]; - } - } - - for (i=0 ; i<128 ; i++) - { - for (j=0 ; j<131 ; j++) - { - if (src[i*256 + (j & 0x7F)]) - { - bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)]; - bottommask[(i*131) + j] = 0; - } - else - { - bottomsky[(i*131) + j] = 0; - bottommask[(i*131) + j] = 0xff; - } - } - } - - r_skysource = newsky; -} - - -/* -================= -R_MakeSky -================= -*/ -void R_MakeSky (void) -{ - int x, y; - int ofs, baseofs; - int xshift, yshift; - unsigned *pnewsky; - static int xlast = -1, ylast = -1; - - xshift = skytime*skyspeed; - yshift = skytime*skyspeed; - - if ((xshift == xlast) && (yshift == ylast)) - return; - - xlast = xshift; - ylast = yshift; - - pnewsky = (unsigned *)&newsky[0]; - - for (y=0 ; yoffsets[0]; + + for (i=0 ; i<128 ; i++) + { + for (j=0 ; j<128 ; j++) + { + newsky[(i*256) + j + 128] = src[i*256 + j + 128]; + } + } + + for (i=0 ; i<128 ; i++) + { + for (j=0 ; j<131 ; j++) + { + if (src[i*256 + (j & 0x7F)]) + { + bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)]; + bottommask[(i*131) + j] = 0; + } + else + { + bottomsky[(i*131) + j] = 0; + bottommask[(i*131) + j] = 0xff; + } + } + } + + r_skysource = newsky; +} + + +/* +================= +R_MakeSky +================= +*/ +void R_MakeSky (void) +{ + int x, y; + int ofs, baseofs; + int xshift, yshift; + unsigned *pnewsky; + static int xlast = -1, ylast = -1; + + xshift = skytime*skyspeed; + yshift = skytime*skyspeed; + + if ((xshift == xlast) && (yshift == ylast)) + return; + + xlast = xshift; + ylast = yshift; + + pnewsky = (unsigned *)&newsky[0]; + + for (y=0 ; ydist; - pclipnormal = pclipplane->normal; - -// calc dists - if (clip_current) - { - in = clip_verts[1][0]; - outstep = clip_verts[0][0]; - clip_current = 0; - } - else - { - in = clip_verts[0][0]; - outstep = clip_verts[1][0]; - clip_current = 1; - } - - instep = in; - for (i=0 ; i= 0) - { - Q_memcpy (outstep, instep, sizeof (vec5_t)); - outstep += sizeof (vec5_t) / sizeof (float); - outcount++; - } - - if (dists[i] == 0 || dists[i+1] == 0) - continue; - - if ( (dists[i] > 0) == (dists[i+1] > 0) ) - continue; - - // split it into a new vertex - frac = dists[i] / (dists[i] - dists[i+1]); - - vert2 = instep + sizeof (vec5_t) / sizeof (float); - - outstep[0] = instep[0] + frac*(vert2[0] - instep[0]); - outstep[1] = instep[1] + frac*(vert2[1] - instep[1]); - outstep[2] = instep[2] + frac*(vert2[2] - instep[2]); - outstep[3] = instep[3] + frac*(vert2[3] - instep[3]); - outstep[4] = instep[4] + frac*(vert2[4] - instep[4]); - - outstep += sizeof (vec5_t) / sizeof (float); - outcount++; - } - - return outcount; -} - - -/* -================ -R_SetupAndDrawSprite -================ -*/ -void R_SetupAndDrawSprite () -{ - int i, nump; - float dot, scale, *pv; - vec5_t *pverts; - vec3_t left, up, right, down, transformed, local; - emitpoint_t outverts[MAXWORKINGVERTS+1], *pout; - - dot = DotProduct (r_spritedesc.vpn, modelorg); - -// backface cull - if (dot >= 0) - return; - -// build the sprite poster in worldspace - VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right); - VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up); - VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left); - VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down); - - pverts = clip_verts[0]; - - pverts[0][0] = r_entorigin[0] + up[0] + left[0]; - pverts[0][1] = r_entorigin[1] + up[1] + left[1]; - pverts[0][2] = r_entorigin[2] + up[2] + left[2]; - pverts[0][3] = 0; - pverts[0][4] = 0; - - pverts[1][0] = r_entorigin[0] + up[0] + right[0]; - pverts[1][1] = r_entorigin[1] + up[1] + right[1]; - pverts[1][2] = r_entorigin[2] + up[2] + right[2]; - pverts[1][3] = sprite_width; - pverts[1][4] = 0; - - pverts[2][0] = r_entorigin[0] + down[0] + right[0]; - pverts[2][1] = r_entorigin[1] + down[1] + right[1]; - pverts[2][2] = r_entorigin[2] + down[2] + right[2]; - pverts[2][3] = sprite_width; - pverts[2][4] = sprite_height; - - pverts[3][0] = r_entorigin[0] + down[0] + left[0]; - pverts[3][1] = r_entorigin[1] + down[1] + left[1]; - pverts[3][2] = r_entorigin[2] + down[2] + left[2]; - pverts[3][3] = 0; - pverts[3][4] = sprite_height; - -// clip to the frustum in worldspace - nump = 4; - clip_current = 0; - - for (i=0 ; i<4 ; i++) - { - nump = R_ClipSpriteFace (nump, &view_clipplanes[i]); - if (nump < 3) - return; - if (nump >= MAXWORKINGVERTS) - Sys_Error("R_SetupAndDrawSprite: too many points"); - } - -// transform vertices into viewspace and project - pv = &clip_verts[clip_current][0][0]; - r_spritedesc.nearzi = -999999; - - for (i=0 ; izi = 1.0 / transformed[2]; - if (pout->zi > r_spritedesc.nearzi) - r_spritedesc.nearzi = pout->zi; - - pout->s = pv[3]; - pout->t = pv[4]; - - scale = xscale * pout->zi; - pout->u = (xcenter + scale * transformed[0]); - - scale = yscale * pout->zi; - pout->v = (ycenter - scale * transformed[1]); - - pv += sizeof (vec5_t) / sizeof (*pv); - } - -// draw it - r_spritedesc.nump = nump; - r_spritedesc.pverts = outverts; - D_DrawSprite (); -} - - -/* -================ -R_GetSpriteframe -================ -*/ -mspriteframe_t *R_GetSpriteframe (msprite_t *psprite) -{ - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - int i, numframes, frame; - float *pintervals, fullinterval, targettime, time; - - frame = currententity->frame; - - if ((frame >= psprite->numframes) || (frame < 0)) - { - Con_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) - { - pspriteframe = psprite->frames[frame].frameptr; - } - else - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - - time = cl.time + currententity->syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by 0 - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - - -/* -================ -R_DrawSprite -================ -*/ -void R_DrawSprite (void) -{ - int i; - msprite_t *psprite; - vec3_t tvec; - float dot, angle, sr, cr; - - psprite = currententity->model->cache.data; - - r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); - - sprite_width = r_spritedesc.pspriteframe->width; - sprite_height = r_spritedesc.pspriteframe->height; - -// TODO: make this caller-selectable - if (psprite->type == SPR_FACING_UPRIGHT) - { - // generate the sprite's axes, with vup straight up in worldspace, and - // r_spritedesc.vright perpendicular to modelorg. - // This will not work if the view direction is very close to straight up or - // down, because the cross product will be between two nearly parallel - // vectors and starts to approach an undefined state, so we don't draw if - // the two vectors are less than 1 degree apart - tvec[0] = -modelorg[0]; - tvec[1] = -modelorg[1]; - tvec[2] = -modelorg[2]; - VectorNormalize (tvec); - dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because - // r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 - return; - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = tvec[1]; - // CrossProduct(r_spritedesc.vup, -modelorg, - r_spritedesc.vright[1] = -tvec[0]; - // r_spritedesc.vright) - r_spritedesc.vright[2] = 0; - VectorNormalize (r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; - // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, - // r_spritedesc.vpn) - } - else if (psprite->type == SPR_VP_PARALLEL) - { - // generate the sprite's axes, completely parallel to the viewplane. There - // are no problem situations, because the sprite is always in the same - // position relative to the viewer - for (i=0 ; i<3 ; i++) - { - r_spritedesc.vup[i] = vup[i]; - r_spritedesc.vright[i] = vright[i]; - r_spritedesc.vpn[i] = vpn[i]; - } - } - else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) - { - // generate the sprite's axes, with vup straight up in worldspace, and - // r_spritedesc.vright parallel to the viewplane. - // This will not work if the view direction is very close to straight up or - // down, because the cross product will be between two nearly parallel - // vectors and starts to approach an undefined state, so we don't draw if - // the two vectors are less than 1 degree apart - dot = vpn[2]; // same as DotProduct (vpn, r_spritedesc.vup) because - // r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 - return; - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = vpn[1]; - // CrossProduct (r_spritedesc.vup, vpn, - r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright) - r_spritedesc.vright[2] = 0; - VectorNormalize (r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; - // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, - // r_spritedesc.vpn) - } - else if (psprite->type == SPR_ORIENTED) - { - // generate the sprite's axes, according to the sprite's world orientation - AngleVectors (currententity->angles, r_spritedesc.vpn, - r_spritedesc.vright, r_spritedesc.vup); - } - else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) - { - // generate the sprite's axes, parallel to the viewplane, but rotated in - // that plane around the center according to the sprite entity's roll - // angle. So vpn stays the same, but vright and vup rotate - angle = currententity->angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - for (i=0 ; i<3 ; i++) - { - r_spritedesc.vpn[i] = vpn[i]; - r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; - r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; - } - } - else - { - Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type); - } - - R_RotateSprite (psprite->beamlength); - - R_SetupAndDrawSprite (); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_sprite.c + +#include "quakedef.h" +#include "r_local.h" + +static int clip_current; +static vec5_t clip_verts[2][MAXWORKINGVERTS]; +static int sprite_width, sprite_height; + +spritedesc_t r_spritedesc; + + +/* +================ +R_RotateSprite +================ +*/ +void R_RotateSprite (float beamlength) +{ + vec3_t vec; + + if (beamlength == 0.0) + return; + + VectorScale (r_spritedesc.vpn, -beamlength, vec); + VectorAdd (r_entorigin, vec, r_entorigin); + VectorSubtract (modelorg, vec, modelorg); +} + + +/* +============= +R_ClipSpriteFace + +Clips the winding at clip_verts[clip_current] and changes clip_current +Throws out the back side +============== +*/ +int R_ClipSpriteFace (int nump, clipplane_t *pclipplane) +{ + int i, outcount; + float dists[MAXWORKINGVERTS+1]; + float frac, clipdist, *pclipnormal; + float *in, *instep, *outstep, *vert2; + + clipdist = pclipplane->dist; + pclipnormal = pclipplane->normal; + +// calc dists + if (clip_current) + { + in = clip_verts[1][0]; + outstep = clip_verts[0][0]; + clip_current = 0; + } + else + { + in = clip_verts[0][0]; + outstep = clip_verts[1][0]; + clip_current = 1; + } + + instep = in; + for (i=0 ; i= 0) + { + Q_memcpy (outstep, instep, sizeof (vec5_t)); + outstep += sizeof (vec5_t) / sizeof (float); + outcount++; + } + + if (dists[i] == 0 || dists[i+1] == 0) + continue; + + if ( (dists[i] > 0) == (dists[i+1] > 0) ) + continue; + + // split it into a new vertex + frac = dists[i] / (dists[i] - dists[i+1]); + + vert2 = instep + sizeof (vec5_t) / sizeof (float); + + outstep[0] = instep[0] + frac*(vert2[0] - instep[0]); + outstep[1] = instep[1] + frac*(vert2[1] - instep[1]); + outstep[2] = instep[2] + frac*(vert2[2] - instep[2]); + outstep[3] = instep[3] + frac*(vert2[3] - instep[3]); + outstep[4] = instep[4] + frac*(vert2[4] - instep[4]); + + outstep += sizeof (vec5_t) / sizeof (float); + outcount++; + } + + return outcount; +} + + +/* +================ +R_SetupAndDrawSprite +================ +*/ +void R_SetupAndDrawSprite () +{ + int i, nump; + float dot, scale, *pv; + vec5_t *pverts; + vec3_t left, up, right, down, transformed, local; + emitpoint_t outverts[MAXWORKINGVERTS+1], *pout; + + dot = DotProduct (r_spritedesc.vpn, modelorg); + +// backface cull + if (dot >= 0) + return; + +// build the sprite poster in worldspace + VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right); + VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up); + VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left); + VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down); + + pverts = clip_verts[0]; + + pverts[0][0] = r_entorigin[0] + up[0] + left[0]; + pverts[0][1] = r_entorigin[1] + up[1] + left[1]; + pverts[0][2] = r_entorigin[2] + up[2] + left[2]; + pverts[0][3] = 0; + pverts[0][4] = 0; + + pverts[1][0] = r_entorigin[0] + up[0] + right[0]; + pverts[1][1] = r_entorigin[1] + up[1] + right[1]; + pverts[1][2] = r_entorigin[2] + up[2] + right[2]; + pverts[1][3] = sprite_width; + pverts[1][4] = 0; + + pverts[2][0] = r_entorigin[0] + down[0] + right[0]; + pverts[2][1] = r_entorigin[1] + down[1] + right[1]; + pverts[2][2] = r_entorigin[2] + down[2] + right[2]; + pverts[2][3] = sprite_width; + pverts[2][4] = sprite_height; + + pverts[3][0] = r_entorigin[0] + down[0] + left[0]; + pverts[3][1] = r_entorigin[1] + down[1] + left[1]; + pverts[3][2] = r_entorigin[2] + down[2] + left[2]; + pverts[3][3] = 0; + pverts[3][4] = sprite_height; + +// clip to the frustum in worldspace + nump = 4; + clip_current = 0; + + for (i=0 ; i<4 ; i++) + { + nump = R_ClipSpriteFace (nump, &view_clipplanes[i]); + if (nump < 3) + return; + if (nump >= MAXWORKINGVERTS) + Sys_Error("R_SetupAndDrawSprite: too many points"); + } + +// transform vertices into viewspace and project + pv = &clip_verts[clip_current][0][0]; + r_spritedesc.nearzi = -999999; + + for (i=0 ; izi = 1.0 / transformed[2]; + if (pout->zi > r_spritedesc.nearzi) + r_spritedesc.nearzi = pout->zi; + + pout->s = pv[3]; + pout->t = pv[4]; + + scale = xscale * pout->zi; + pout->u = (xcenter + scale * transformed[0]); + + scale = yscale * pout->zi; + pout->v = (ycenter - scale * transformed[1]); + + pv += sizeof (vec5_t) / sizeof (*pv); + } + +// draw it + r_spritedesc.nump = nump; + r_spritedesc.pverts = outverts; + D_DrawSprite (); +} + + +/* +================ +R_GetSpriteframe +================ +*/ +mspriteframe_t *R_GetSpriteframe (msprite_t *psprite) +{ + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, numframes, frame; + float *pintervals, fullinterval, targettime, time; + + frame = currententity->frame; + + if ((frame >= psprite->numframes) || (frame < 0)) + { + Con_Printf ("R_DrawSprite: no such frame %d\n", frame); + frame = 0; + } + + if (psprite->frames[frame].type == SPR_SINGLE) + { + pspriteframe = psprite->frames[frame].frameptr; + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + + time = cl.time + currententity->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + for (i=0 ; i<(numframes-1) ; i++) + { + if (pintervals[i] > targettime) + break; + } + + pspriteframe = pspritegroup->frames[i]; + } + + return pspriteframe; +} + + +/* +================ +R_DrawSprite +================ +*/ +void R_DrawSprite (void) +{ + int i; + msprite_t *psprite; + vec3_t tvec; + float dot, angle, sr, cr; + + psprite = currententity->model->cache.data; + + r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); + + sprite_width = r_spritedesc.pspriteframe->width; + sprite_height = r_spritedesc.pspriteframe->height; + +// TODO: make this caller-selectable + if (psprite->type == SPR_FACING_UPRIGHT) + { + // generate the sprite's axes, with vup straight up in worldspace, and + // r_spritedesc.vright perpendicular to modelorg. + // This will not work if the view direction is very close to straight up or + // down, because the cross product will be between two nearly parallel + // vectors and starts to approach an undefined state, so we don't draw if + // the two vectors are less than 1 degree apart + tvec[0] = -modelorg[0]; + tvec[1] = -modelorg[1]; + tvec[2] = -modelorg[2]; + VectorNormalize (tvec); + dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because + // r_spritedesc.vup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 + return; + r_spritedesc.vup[0] = 0; + r_spritedesc.vup[1] = 0; + r_spritedesc.vup[2] = 1; + r_spritedesc.vright[0] = tvec[1]; + // CrossProduct(r_spritedesc.vup, -modelorg, + r_spritedesc.vright[1] = -tvec[0]; + // r_spritedesc.vright) + r_spritedesc.vright[2] = 0; + VectorNormalize (r_spritedesc.vright); + r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; + r_spritedesc.vpn[1] = r_spritedesc.vright[0]; + r_spritedesc.vpn[2] = 0; + // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, + // r_spritedesc.vpn) + } + else if (psprite->type == SPR_VP_PARALLEL) + { + // generate the sprite's axes, completely parallel to the viewplane. There + // are no problem situations, because the sprite is always in the same + // position relative to the viewer + for (i=0 ; i<3 ; i++) + { + r_spritedesc.vup[i] = vup[i]; + r_spritedesc.vright[i] = vright[i]; + r_spritedesc.vpn[i] = vpn[i]; + } + } + else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) + { + // generate the sprite's axes, with vup straight up in worldspace, and + // r_spritedesc.vright parallel to the viewplane. + // This will not work if the view direction is very close to straight up or + // down, because the cross product will be between two nearly parallel + // vectors and starts to approach an undefined state, so we don't draw if + // the two vectors are less than 1 degree apart + dot = vpn[2]; // same as DotProduct (vpn, r_spritedesc.vup) because + // r_spritedesc.vup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 + return; + r_spritedesc.vup[0] = 0; + r_spritedesc.vup[1] = 0; + r_spritedesc.vup[2] = 1; + r_spritedesc.vright[0] = vpn[1]; + // CrossProduct (r_spritedesc.vup, vpn, + r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright) + r_spritedesc.vright[2] = 0; + VectorNormalize (r_spritedesc.vright); + r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; + r_spritedesc.vpn[1] = r_spritedesc.vright[0]; + r_spritedesc.vpn[2] = 0; + // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, + // r_spritedesc.vpn) + } + else if (psprite->type == SPR_ORIENTED) + { + // generate the sprite's axes, according to the sprite's world orientation + AngleVectors (currententity->angles, r_spritedesc.vpn, + r_spritedesc.vright, r_spritedesc.vup); + } + else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) + { + // generate the sprite's axes, parallel to the viewplane, but rotated in + // that plane around the center according to the sprite entity's roll + // angle. So vpn stays the same, but vright and vup rotate + angle = currententity->angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + for (i=0 ; i<3 ; i++) + { + r_spritedesc.vpn[i] = vpn[i]; + r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; + r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; + } + } + else + { + Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type); + } + + R_RotateSprite (psprite->beamlength); + + R_SetupAndDrawSprite (); +} + diff --git a/WinQuake/r_surf.c b/WinQuake/r_surf.c index a2436d5..00a1391 100644 --- a/WinQuake/r_surf.c +++ b/WinQuake/r_surf.c @@ -1,678 +1,678 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_surf.c: surface-related refresh code - -#include "quakedef.h" -#include "r_local.h" - -drawsurf_t r_drawsurf; - -int lightleft, sourcesstep, blocksize, sourcetstep; -int lightdelta, lightdeltastep; -int lightright, lightleftstep, lightrightstep, blockdivshift; -unsigned blockdivmask; -void *prowdestbase; -unsigned char *pbasesource; -int surfrowbytes; // used by ASM files -unsigned *r_lightptr; -int r_stepback; -int r_lightwidth; -int r_numhblocks, r_numvblocks; -unsigned char *r_source, *r_sourcemax; - -void R_DrawSurfaceBlock8_mip0 (void); -void R_DrawSurfaceBlock8_mip1 (void); -void R_DrawSurfaceBlock8_mip2 (void); -void R_DrawSurfaceBlock8_mip3 (void); - -static void (*surfmiptable[4])(void) = { - R_DrawSurfaceBlock8_mip0, - R_DrawSurfaceBlock8_mip1, - R_DrawSurfaceBlock8_mip2, - R_DrawSurfaceBlock8_mip3 -}; - - - -unsigned blocklights[18*18]; - -/* -=============== -R_AddDynamicLights -=============== -*/ -void R_AddDynamicLights (void) -{ - msurface_t *surf; - int lnum; - int sd, td; - float dist, rad, minlight; - vec3_t impact, local; - int s, t; - int i; - int smax, tmax; - mtexinfo_t *tex; - - surf = r_drawsurf.surf; - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; - tex = surf->texinfo; - - for (lnum=0 ; lnumdlightbits & (1<plane->normal) - - surf->plane->dist; - rad -= fabs(dist); - minlight = cl_dlights[lnum].minlight; - if (rad < minlight) - continue; - minlight = rad - minlight; - - for (i=0 ; i<3 ; i++) - { - impact[i] = cl_dlights[lnum].origin[i] - - surf->plane->normal[i]*dist; - } - - local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; - local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; - - local[0] -= surf->texturemins[0]; - local[1] -= surf->texturemins[1]; - - for (t = 0 ; t td) - dist = sd + (td>>1); - else - dist = td + (sd>>1); - if (dist < minlight) -#ifdef QUAKE2 - { - unsigned temp; - temp = (rad - dist)*256; - i = t*smax + s; - if (!cl_dlights[lnum].dark) - blocklights[i] += temp; - else - { - if (blocklights[i] > temp) - blocklights[i] -= temp; - else - blocklights[i] = 0; - } - } -#else - blocklights[t*smax + s] += (rad - dist)*256; -#endif - } - } - } -} - -/* -=============== -R_BuildLightMap - -Combine and scale multiple lightmaps into the 8.8 format in blocklights -=============== -*/ -void R_BuildLightMap (void) -{ - int smax, tmax; - int t; - int i, size; - byte *lightmap; - unsigned scale; - int maps; - msurface_t *surf; - - surf = r_drawsurf.surf; - - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; - size = smax*tmax; - lightmap = surf->samples; - - if (r_fullbright.value || !cl.worldmodel->lightdata) - { - for (i=0 ; istyles[maps] != 255 ; - maps++) - { - scale = r_drawsurf.lightadj[maps]; // 8.8 fraction - for (i=0 ; idlightframe == r_framecount) - R_AddDynamicLights (); - -// bound, invert, and shift - for (i=0 ; i> (8 - VID_CBITS); - - if (t < (1 << 6)) - t = (1 << 6); - - blocklights[i] = t; - } -} - - -/* -=============== -R_TextureAnimation - -Returns the proper texture for a given time and base texture -=============== -*/ -texture_t *R_TextureAnimation (texture_t *base) -{ - int reletive; - int count; - - if (currententity->frame) - { - if (base->alternate_anims) - base = base->alternate_anims; - } - - if (!base->anim_total) - return base; - - reletive = (int)(cl.time*10) % base->anim_total; - - count = 0; - while (base->anim_min > reletive || base->anim_max <= reletive) - { - base = base->anim_next; - if (!base) - Sys_Error ("R_TextureAnimation: broken cycle"); - if (++count > 100) - Sys_Error ("R_TextureAnimation: infinite cycle"); - } - - return base; -} - - -/* -=============== -R_DrawSurface -=============== -*/ -void R_DrawSurface (void) -{ - unsigned char *basetptr; - int smax, tmax, twidth; - int u; - int soffset, basetoffset, texwidth; - int horzblockstep; - unsigned char *pcolumndest; - void (*pblockdrawer)(void); - texture_t *mt; - -// calculate the lightings - R_BuildLightMap (); - - surfrowbytes = r_drawsurf.rowbytes; - - mt = r_drawsurf.texture; - - r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip]; - -// the fractional light values should range from 0 to (VID_GRADES - 1) << 16 -// from a source range of 0 - 255 - - texwidth = mt->width >> r_drawsurf.surfmip; - - blocksize = 16 >> r_drawsurf.surfmip; - blockdivshift = 4 - r_drawsurf.surfmip; - blockdivmask = (1 << blockdivshift) - 1; - - r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; - - r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; - r_numvblocks = r_drawsurf.surfheight >> blockdivshift; - -//============================== - - if (r_pixbytes == 1) - { - pblockdrawer = surfmiptable[r_drawsurf.surfmip]; - // TODO: only needs to be set when there is a display settings change - horzblockstep = blocksize; - } - else - { - pblockdrawer = R_DrawSurfaceBlock16; - // TODO: only needs to be set when there is a display settings change - horzblockstep = blocksize << 1; - } - - smax = mt->width >> r_drawsurf.surfmip; - twidth = texwidth; - tmax = mt->height >> r_drawsurf.surfmip; - sourcetstep = texwidth; - r_stepback = tmax * twidth; - - r_sourcemax = r_source + (tmax * smax); - - soffset = r_drawsurf.surf->texturemins[0]; - basetoffset = r_drawsurf.surf->texturemins[1]; - -// << 16 components are to guarantee positive values for % - soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; - basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) - + (tmax << 16)) % tmax) * twidth)]; - - pcolumndest = r_drawsurf.surfdat; - - for (u=0 ; u= smax) - soffset = 0; - - pcolumndest += horzblockstep; - } -} - - -//============================================================================= - -#if !id386 - -/* -================ -R_DrawSurfaceBlock8_mip0 -================ -*/ -void R_DrawSurfaceBlock8_mip0 (void) -{ - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; - - psource = pbasesource; - prowdest = prowdestbase; - - for (v=0 ; v> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (i=0 ; i<16 ; i++) - { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 4; - - light = lightright; - - for (b=15; b>=0; b--) - { - pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - - -/* -================ -R_DrawSurfaceBlock8_mip1 -================ -*/ -void R_DrawSurfaceBlock8_mip1 (void) -{ - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; - - psource = pbasesource; - prowdest = prowdestbase; - - for (v=0 ; v> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (i=0 ; i<8 ; i++) - { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 3; - - light = lightright; - - for (b=7; b>=0; b--) - { - pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - - -/* -================ -R_DrawSurfaceBlock8_mip2 -================ -*/ -void R_DrawSurfaceBlock8_mip2 (void) -{ - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; - - psource = pbasesource; - prowdest = prowdestbase; - - for (v=0 ; v> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (i=0 ; i<4 ; i++) - { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 2; - - light = lightright; - - for (b=3; b>=0; b--) - { - pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - - -/* -================ -R_DrawSurfaceBlock8_mip3 -================ -*/ -void R_DrawSurfaceBlock8_mip3 (void) -{ - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; - - psource = pbasesource; - prowdest = prowdestbase; - - for (v=0 ; v> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - for (i=0 ; i<2 ; i++) - { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 1; - - light = lightright; - - for (b=1; b>=0; b--) - { - pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - - -/* -================ -R_DrawSurfaceBlock16 - -FIXME: make this work -================ -*/ -void R_DrawSurfaceBlock16 (void) -{ - int k; - unsigned char *psource; - int lighttemp, lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *)prowdestbase; - - for (k=0 ; k> blockdivshift; - - light = lightleft; - pdest = prowdest; - - for (b=0; b> 16) & 63; - t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63; - *pd++ = *(pbasetex + (t<<6) + s); - } - } -} - - -/* -================ -R_GenTurbTile16 -================ -*/ -void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest) -{ - int *turb; - int i, j, s, t; - unsigned short *pd; - - turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1)); - pd = (unsigned short *)pdest; - - for (i=0 ; i> 16) & 63; - t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63; - *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)]; - } - } -} - - -/* -================ -R_GenTile -================ -*/ -void R_GenTile (msurface_t *psurf, void *pdest) -{ - if (psurf->flags & SURF_DRAWTURB) - { - if (r_pixbytes == 1) - { - R_GenTurbTile ((pixel_t *) - ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); - } - else - { - R_GenTurbTile16 ((pixel_t *) - ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); - } - } - else if (psurf->flags & SURF_DRAWSKY) - { - if (r_pixbytes == 1) - { - R_GenSkyTile (pdest); - } - else - { - R_GenSkyTile16 (pdest); - } - } - else - { - Sys_Error ("Unknown tile type"); - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_surf.c: surface-related refresh code + +#include "quakedef.h" +#include "r_local.h" + +drawsurf_t r_drawsurf; + +int lightleft, sourcesstep, blocksize, sourcetstep; +int lightdelta, lightdeltastep; +int lightright, lightleftstep, lightrightstep, blockdivshift; +unsigned blockdivmask; +void *prowdestbase; +unsigned char *pbasesource; +int surfrowbytes; // used by ASM files +unsigned *r_lightptr; +int r_stepback; +int r_lightwidth; +int r_numhblocks, r_numvblocks; +unsigned char *r_source, *r_sourcemax; + +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); + +static void (*surfmiptable[4])(void) = { + R_DrawSurfaceBlock8_mip0, + R_DrawSurfaceBlock8_mip1, + R_DrawSurfaceBlock8_mip2, + R_DrawSurfaceBlock8_mip3 +}; + + + +unsigned blocklights[18*18]; + +/* +=============== +R_AddDynamicLights +=============== +*/ +void R_AddDynamicLights (void) +{ + msurface_t *surf; + int lnum; + int sd, td; + float dist, rad, minlight; + vec3_t impact, local; + int s, t; + int i; + int smax, tmax; + mtexinfo_t *tex; + + surf = r_drawsurf.surf; + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + tex = surf->texinfo; + + for (lnum=0 ; lnumdlightbits & (1<plane->normal) - + surf->plane->dist; + rad -= fabs(dist); + minlight = cl_dlights[lnum].minlight; + if (rad < minlight) + continue; + minlight = rad - minlight; + + for (i=0 ; i<3 ; i++) + { + impact[i] = cl_dlights[lnum].origin[i] - + surf->plane->normal[i]*dist; + } + + local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; + local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; + + local[0] -= surf->texturemins[0]; + local[1] -= surf->texturemins[1]; + + for (t = 0 ; t td) + dist = sd + (td>>1); + else + dist = td + (sd>>1); + if (dist < minlight) +#ifdef QUAKE2 + { + unsigned temp; + temp = (rad - dist)*256; + i = t*smax + s; + if (!cl_dlights[lnum].dark) + blocklights[i] += temp; + else + { + if (blocklights[i] > temp) + blocklights[i] -= temp; + else + blocklights[i] = 0; + } + } +#else + blocklights[t*smax + s] += (rad - dist)*256; +#endif + } + } + } +} + +/* +=============== +R_BuildLightMap + +Combine and scale multiple lightmaps into the 8.8 format in blocklights +=============== +*/ +void R_BuildLightMap (void) +{ + int smax, tmax; + int t; + int i, size; + byte *lightmap; + unsigned scale; + int maps; + msurface_t *surf; + + surf = r_drawsurf.surf; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + size = smax*tmax; + lightmap = surf->samples; + + if (r_fullbright.value || !cl.worldmodel->lightdata) + { + for (i=0 ; istyles[maps] != 255 ; + maps++) + { + scale = r_drawsurf.lightadj[maps]; // 8.8 fraction + for (i=0 ; idlightframe == r_framecount) + R_AddDynamicLights (); + +// bound, invert, and shift + for (i=0 ; i> (8 - VID_CBITS); + + if (t < (1 << 6)) + t = (1 << 6); + + blocklights[i] = t; + } +} + + +/* +=============== +R_TextureAnimation + +Returns the proper texture for a given time and base texture +=============== +*/ +texture_t *R_TextureAnimation (texture_t *base) +{ + int reletive; + int count; + + if (currententity->frame) + { + if (base->alternate_anims) + base = base->alternate_anims; + } + + if (!base->anim_total) + return base; + + reletive = (int)(cl.time*10) % base->anim_total; + + count = 0; + while (base->anim_min > reletive || base->anim_max <= reletive) + { + base = base->anim_next; + if (!base) + Sys_Error ("R_TextureAnimation: broken cycle"); + if (++count > 100) + Sys_Error ("R_TextureAnimation: infinite cycle"); + } + + return base; +} + + +/* +=============== +R_DrawSurface +=============== +*/ +void R_DrawSurface (void) +{ + unsigned char *basetptr; + int smax, tmax, twidth; + int u; + int soffset, basetoffset, texwidth; + int horzblockstep; + unsigned char *pcolumndest; + void (*pblockdrawer)(void); + texture_t *mt; + +// calculate the lightings + R_BuildLightMap (); + + surfrowbytes = r_drawsurf.rowbytes; + + mt = r_drawsurf.texture; + + r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip]; + +// the fractional light values should range from 0 to (VID_GRADES - 1) << 16 +// from a source range of 0 - 255 + + texwidth = mt->width >> r_drawsurf.surfmip; + + blocksize = 16 >> r_drawsurf.surfmip; + blockdivshift = 4 - r_drawsurf.surfmip; + blockdivmask = (1 << blockdivshift) - 1; + + r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; + + r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; + r_numvblocks = r_drawsurf.surfheight >> blockdivshift; + +//============================== + + if (r_pixbytes == 1) + { + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; + // TODO: only needs to be set when there is a display settings change + horzblockstep = blocksize; + } + else + { + pblockdrawer = R_DrawSurfaceBlock16; + // TODO: only needs to be set when there is a display settings change + horzblockstep = blocksize << 1; + } + + smax = mt->width >> r_drawsurf.surfmip; + twidth = texwidth; + tmax = mt->height >> r_drawsurf.surfmip; + sourcetstep = texwidth; + r_stepback = tmax * twidth; + + r_sourcemax = r_source + (tmax * smax); + + soffset = r_drawsurf.surf->texturemins[0]; + basetoffset = r_drawsurf.surf->texturemins[1]; + +// << 16 components are to guarantee positive values for % + soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; + basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth)]; + + pcolumndest = r_drawsurf.surfdat; + + for (u=0 ; u= smax) + soffset = 0; + + pcolumndest += horzblockstep; + } +} + + +//============================================================================= + +#if !id386 + +/* +================ +R_DrawSurfaceBlock8_mip0 +================ +*/ +void R_DrawSurfaceBlock8_mip0 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (i=0 ; i<16 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 4; + + light = lightright; + + for (b=15; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip1 +================ +*/ +void R_DrawSurfaceBlock8_mip1 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (i=0 ; i<8 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 3; + + light = lightright; + + for (b=7; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip2 +================ +*/ +void R_DrawSurfaceBlock8_mip2 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (i=0 ; i<4 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 2; + + light = lightright; + + for (b=3; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip3 +================ +*/ +void R_DrawSurfaceBlock8_mip3 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + for (i=0 ; i<2 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 1; + + light = lightright; + + for (b=1; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock16 + +FIXME: make this work +================ +*/ +void R_DrawSurfaceBlock16 (void) +{ + int k; + unsigned char *psource; + int lighttemp, lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *)prowdestbase; + + for (k=0 ; k> blockdivshift; + + light = lightleft; + pdest = prowdest; + + for (b=0; b> 16) & 63; + t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63; + *pd++ = *(pbasetex + (t<<6) + s); + } + } +} + + +/* +================ +R_GenTurbTile16 +================ +*/ +void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest) +{ + int *turb; + int i, j, s, t; + unsigned short *pd; + + turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1)); + pd = (unsigned short *)pdest; + + for (i=0 ; i> 16) & 63; + t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63; + *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)]; + } + } +} + + +/* +================ +R_GenTile +================ +*/ +void R_GenTile (msurface_t *psurf, void *pdest) +{ + if (psurf->flags & SURF_DRAWTURB) + { + if (r_pixbytes == 1) + { + R_GenTurbTile ((pixel_t *) + ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); + } + else + { + R_GenTurbTile16 ((pixel_t *) + ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); + } + } + else if (psurf->flags & SURF_DRAWSKY) + { + if (r_pixbytes == 1) + { + R_GenSkyTile (pdest); + } + else + { + R_GenSkyTile16 (pdest); + } + } + else + { + Sys_Error ("Unknown tile type"); + } +} + diff --git a/WinQuake/r_vars.c b/WinQuake/r_vars.c index eb41290..90fe7f5 100644 --- a/WinQuake/r_vars.c +++ b/WinQuake/r_vars.c @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_vars.c: global refresh variables - -#include "quakedef.h" - -#if !id386 - -// all global and static refresh variables are collected in a contiguous block -// to avoid cache conflicts. - -//------------------------------------------------------- -// global refresh variables -//------------------------------------------------------- - -// FIXME: make into one big structure, like cl or sv -// FIXME: do separately for refresh engine and driver - -int r_bmodelactive; - -#endif // !id386 - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_vars.c: global refresh variables + +#include "quakedef.h" + +#if !id386 + +// all global and static refresh variables are collected in a contiguous block +// to avoid cache conflicts. + +//------------------------------------------------------- +// global refresh variables +//------------------------------------------------------- + +// FIXME: make into one big structure, like cl or sv +// FIXME: do separately for refresh engine and driver + +int r_bmodelactive; + +#endif // !id386 + diff --git a/WinQuake/r_varsa.s b/WinQuake/r_varsa.s index 2c3f9e5..0b1cda0 100644 --- a/WinQuake/r_varsa.s +++ b/WinQuake/r_varsa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // r_varsa.s // diff --git a/WinQuake/render.h b/WinQuake/render.h index b5f8382..30638d7 100644 --- a/WinQuake/render.h +++ b/WinQuake/render.h @@ -1,158 +1,158 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// refresh.h -- public interface to refresh functions - -#define MAXCLIPPLANES 11 - -#define TOP_RANGE 16 // soldier uniform colors -#define BOTTOM_RANGE 96 - -//============================================================================= - -typedef struct efrag_s -{ - struct mleaf_s *leaf; - struct efrag_s *leafnext; - struct entity_s *entity; - struct efrag_s *entnext; -} efrag_t; - - -typedef struct entity_s -{ - qboolean forcelink; // model changed - - int update_type; - - entity_state_t baseline; // to fill in defaults in updates - - double msgtime; // time of last update - vec3_t msg_origins[2]; // last two updates (0 is newest) - vec3_t origin; - vec3_t msg_angles[2]; // last two updates (0 is newest) - vec3_t angles; - struct model_s *model; // NULL = no model - struct efrag_s *efrag; // linked list of efrags - int frame; - float syncbase; // for client-side animations - byte *colormap; - int effects; // light, particals, etc - int skinnum; // for Alias models - int visframe; // last frame this entity was - // found in an active leaf - - int dlightframe; // dynamic lighting - int dlightbits; - -// FIXME: could turn these into a union - int trivial_accept; - struct mnode_s *topnode; // for bmodels, first world node - // that splits bmodel, or NULL if - // not split -} entity_t; - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct -{ - vrect_t vrect; // subwindow in video for refresh - // FIXME: not need vrect next field here? - vrect_t aliasvrect; // scaled Alias version - int vrectright, vrectbottom; // right & bottom screen coords - int aliasvrectright, aliasvrectbottom; // scaled Alias versions - float vrectrightedge; // rightmost right edge we care about, - // for use in edge list - float fvrectx, fvrecty; // for floating-point compares - float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping - int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 - int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 - float fvrectright_adj, fvrectbottom_adj; - // right and bottom edges, for clamping - float fvrectright; // rightmost edge, for Alias clamping - float fvrectbottom; // bottommost edge, for Alias clamping - float horizontalFieldOfView; // at Z = 1.0, this many X is visible - // 2.0 = 90 degrees - float xOrigin; // should probably allways be 0.5 - float yOrigin; // between be around 0.3 to 0.5 - - vec3_t vieworg; - vec3_t viewangles; - - float fov_x, fov_y; - - int ambientlight; -} refdef_t; - - -// -// refresh -// -extern int reinit_surfcache; - - -extern refdef_t r_refdef; -extern vec3_t r_origin, vpn, vright, vup; - -extern struct texture_s *r_notexture_mip; - - -void R_Init (void); -void R_InitTextures (void); -void R_InitEfrags (void); -void R_RenderView (void); // must set r_refdef first -void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); - // called whenever r_refdef or vid change -void R_InitSky (struct texture_s *mt); // called at level load - -void R_AddEfrags (entity_t *ent); -void R_RemoveEfrags (entity_t *ent); - -void R_NewMap (void); - - -void R_ParseParticleEffect (void); -void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); -void R_RocketTrail (vec3_t start, vec3_t end, int type); - -#ifdef QUAKE2 -void R_DarkFieldParticles (entity_t *ent); -#endif -void R_EntityParticles (entity_t *ent); -void R_BlobExplosion (vec3_t org); -void R_ParticleExplosion (vec3_t org); -void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); -void R_LavaSplash (vec3_t org); -void R_TeleportSplash (vec3_t org); - -void R_PushDlights (void); - - -// -// surface cache related -// -extern int reinit_surfcache; // if 1, surface cache is currently empty and -extern qboolean r_cache_thrash; // set if thrashing the surface cache - -int D_SurfaceCacheForRes (int width, int height); -void D_FlushCaches (void); -void D_DeleteSurfaceCache (void); -void D_InitCaches (void *buffer, int size); -void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// refresh.h -- public interface to refresh functions + +#define MAXCLIPPLANES 11 + +#define TOP_RANGE 16 // soldier uniform colors +#define BOTTOM_RANGE 96 + +//============================================================================= + +typedef struct efrag_s +{ + struct mleaf_s *leaf; + struct efrag_s *leafnext; + struct entity_s *entity; + struct efrag_s *entnext; +} efrag_t; + + +typedef struct entity_s +{ + qboolean forcelink; // model changed + + int update_type; + + entity_state_t baseline; // to fill in defaults in updates + + double msgtime; // time of last update + vec3_t msg_origins[2]; // last two updates (0 is newest) + vec3_t origin; + vec3_t msg_angles[2]; // last two updates (0 is newest) + vec3_t angles; + struct model_s *model; // NULL = no model + struct efrag_s *efrag; // linked list of efrags + int frame; + float syncbase; // for client-side animations + byte *colormap; + int effects; // light, particals, etc + int skinnum; // for Alias models + int visframe; // last frame this entity was + // found in an active leaf + + int dlightframe; // dynamic lighting + int dlightbits; + +// FIXME: could turn these into a union + int trivial_accept; + struct mnode_s *topnode; // for bmodels, first world node + // that splits bmodel, or NULL if + // not split +} entity_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + vrect_t vrect; // subwindow in video for refresh + // FIXME: not need vrect next field here? + vrect_t aliasvrect; // scaled Alias version + int vrectright, vrectbottom; // right & bottom screen coords + int aliasvrectright, aliasvrectbottom; // scaled Alias versions + float vrectrightedge; // rightmost right edge we care about, + // for use in edge list + float fvrectx, fvrecty; // for floating-point compares + float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping + int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 + int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 + float fvrectright_adj, fvrectbottom_adj; + // right and bottom edges, for clamping + float fvrectright; // rightmost edge, for Alias clamping + float fvrectbottom; // bottommost edge, for Alias clamping + float horizontalFieldOfView; // at Z = 1.0, this many X is visible + // 2.0 = 90 degrees + float xOrigin; // should probably allways be 0.5 + float yOrigin; // between be around 0.3 to 0.5 + + vec3_t vieworg; + vec3_t viewangles; + + float fov_x, fov_y; + + int ambientlight; +} refdef_t; + + +// +// refresh +// +extern int reinit_surfcache; + + +extern refdef_t r_refdef; +extern vec3_t r_origin, vpn, vright, vup; + +extern struct texture_s *r_notexture_mip; + + +void R_Init (void); +void R_InitTextures (void); +void R_InitEfrags (void); +void R_RenderView (void); // must set r_refdef first +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); + // called whenever r_refdef or vid change +void R_InitSky (struct texture_s *mt); // called at level load + +void R_AddEfrags (entity_t *ent); +void R_RemoveEfrags (entity_t *ent); + +void R_NewMap (void); + + +void R_ParseParticleEffect (void); +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); +void R_RocketTrail (vec3_t start, vec3_t end, int type); + +#ifdef QUAKE2 +void R_DarkFieldParticles (entity_t *ent); +#endif +void R_EntityParticles (entity_t *ent); +void R_BlobExplosion (vec3_t org); +void R_ParticleExplosion (vec3_t org); +void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); +void R_LavaSplash (vec3_t org); +void R_TeleportSplash (vec3_t org); + +void R_PushDlights (void); + + +// +// surface cache related +// +extern int reinit_surfcache; // if 1, surface cache is currently empty and +extern qboolean r_cache_thrash; // set if thrashing the surface cache + +int D_SurfaceCacheForRes (int width, int height); +void D_FlushCaches (void); +void D_DeleteSurfaceCache (void); +void D_InitCaches (void *buffer, int size); +void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); + diff --git a/WinQuake/resource.h b/WinQuake/resource.h index afabb2e..a72295f 100644 --- a/WinQuake/resource.h +++ b/WinQuake/resource.h @@ -1,20 +1,20 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by winquake.rc -// -#define IDS_STRING1 1 -#define IDI_ICON2 1 -#define IDD_DIALOG1 108 -#define IDD_PROGRESS 109 -#define IDC_PROGRESS 1000 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 111 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1004 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by winquake.rc +// +#define IDS_STRING1 1 +#define IDI_ICON2 1 +#define IDD_DIALOG1 108 +#define IDD_PROGRESS 109 +#define IDC_PROGRESS 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/WinQuake/sbar.c b/WinQuake/sbar.c index be9ec9c..db98cb0 100644 --- a/WinQuake/sbar.c +++ b/WinQuake/sbar.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // sbar.c -- status bar code #include "quakedef.h" diff --git a/WinQuake/sbar.h b/WinQuake/sbar.h index 286b3b6..6a1d839 100644 --- a/WinQuake/sbar.h +++ b/WinQuake/sbar.h @@ -1,39 +1,39 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// the status bar is only redrawn if something has changed, but if anything -// does, the entire thing will be redrawn for the next vid.numpages frames. - -#define SBAR_HEIGHT 24 - -extern int sb_lines; // scan lines to draw - -void Sbar_Init (void); - -void Sbar_Changed (void); -// call whenever any of the client stats represented on the sbar changes - -void Sbar_Draw (void); -// called every frame by screen - -void Sbar_IntermissionOverlay (void); -// called each frame after the level has been completed - -void Sbar_FinaleOverlay (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// the status bar is only redrawn if something has changed, but if anything +// does, the entire thing will be redrawn for the next vid.numpages frames. + +#define SBAR_HEIGHT 24 + +extern int sb_lines; // scan lines to draw + +void Sbar_Init (void); + +void Sbar_Changed (void); +// call whenever any of the client stats represented on the sbar changes + +void Sbar_Draw (void); +// called every frame by screen + +void Sbar_IntermissionOverlay (void); +// called each frame after the level has been completed + +void Sbar_FinaleOverlay (void); diff --git a/WinQuake/scitech/INCLUDE/DEBUG.H b/WinQuake/scitech/INCLUDE/DEBUG.H index 1e93676..6a5c945 100644 --- a/WinQuake/scitech/INCLUDE/DEBUG.H +++ b/WinQuake/scitech/INCLUDE/DEBUG.H @@ -1,290 +1,290 @@ -/**************************************************************************** -* -* Copyright (C) 1996 SciTech Software -* All rights reserved. -* -* Filename: $Workfile: debug.h $ -* Version: $Revision: 1.17 $ -* -* Language: ANSI C -* Environment: any -* -* Description: General header file for operating system portable code. -* -* $Date: 04 Mar 1997 11:34:08 $ $Author: KendallB $ -* -****************************************************************************/ - -#ifndef __DEBUG_H -#define __DEBUG_H - -/* We have the following defines to identify the compilation environment: - * - * __16BIT__ Compiling for 16 bit code (any environment) - * __32BIT__ Compiling for 32 bit code (any environment) - * __MSDOS__ Compiling for MS-DOS (includes __WINDOWS16__, __WIN386__) - * __REALDOS__ Compiling for MS-DOS (excludes __WINDOWS16__) - * __MSDOS16__ Compiling for 16 bit MS-DOS - * __MSDOS32__ Compiling for 32 bit MS-DOS - * __WINDOWS__ Compiling for Windows - * __WINDOWS16__ Compiling for 16 bit Windows (__MSDOS__ also defined) - * __WINDOWS32__ Compiling for 32 bit Windows - * __WIN386__ Compiling for Watcom C++ Win386 extended Windows - * __OS2__ Compiling for OS/2 - * __OS2_16__ Compiling for 16 bit OS/2 - * __OS2_32__ Compiling for 32 bit OS/2 - * __UNIX__ Compiling for Unix - * - */ - -#ifdef __SC__ -#if __INTSIZE == 4 -#define __SC386__ -#endif -#endif - -#ifdef __GNUC__ -#define __cdecl /* GCC doesn't know about __cdecl modifiers */ -#define __FLAT__ /* GCC is always 32 bit flat model */ -#define __HAS_BOOL__ /* Latest GNU C++ has bool type */ -#endif - -#ifdef __BORLANDC__ -#if (__BORLANDC__ >= 0x500) || defined(CLASSLIB_DEFS_H) -#define __HAS_BOOL__ /* Borland C++ 5.0 and later define bool type */ -#endif -#endif - -/* For the Metaware High C/C++ compiler, there is no _cdecl calling - * convention. The conventions can be changed, but it is a complicated - * process involving #pragmas, and all externally referenced functions - * will use stack based calling conventions. We also need to change the - * global aliasing conventions to use underscores for external function - * and variables names, so that our assembler routines will link - * correctly (except of course the main function - man what a PAIN!). - */ - -#ifdef __HIGHC__ -#define __cdecl -#define __FLAT__ /* High C is always 32 bit flat model */ -#pragma Global_aliasing_convention("_%r") -extern main(); -#pragma Alias(main,"main") -#endif - -#if defined(__MSDOS__) || defined(__DOS__) || defined(__DPMI32__) || (defined(M_I86) && !defined(__SC386__)) -#ifndef __MSDOS__ -#define __MSDOS__ -#endif -#if defined(__386__) || defined(__FLAT__) || defined(__NT__) || defined(__SC386__) -#ifndef __MSDOS32__ -#define __MSDOS32__ -#endif -#ifndef __32BIT__ -#define __32BIT__ -#endif -#ifndef __REALDOS__ -#define __REALDOS__ -#endif -#elif (defined(_Windows) || defined(_WINDOWS)) && !defined(__DPMI16__) -#ifndef __16BIT__ -#define __16BIT__ -#endif -#ifndef __WINDOWS16__ -#define __WINDOWS16__ -#endif -#ifndef __WINDOWS__ -#define __WINDOWS__ -#endif -#ifndef __MSDOS__ -#define __MSDOS__ -#endif -#else -#ifndef __16BIT__ -#define __16BIT__ -#endif -#ifndef __MSDOS16__ -#define __MSDOS16__ -#endif -#ifndef __REALDOS__ -#define __REALDOS__ -#endif -#endif -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) -#ifndef __32BIT__ -#define __32BIT__ -#endif -#ifndef __WINDOWS32__ -#define __WINDOWS32__ -#endif -#ifndef _WIN32 -#define _WIN32 /* Microsoft Win32 SDK headers use _WIN32 */ -#endif -#ifndef WIN32 -#define WIN32 /* OpenGL headers use WIN32 */ -#endif -#ifndef __WINDOWS__ -#define __WINDOWS__ -#endif -#elif defined(__WINDOWS_386__) -#ifndef __32BIT__ -#define __32BIT__ -#endif -#ifndef __WIN386__ -#define __WIN386__ -#endif -#ifndef __WINDOWS__ -#define __WINDOWS__ -#endif -#ifndef __MSDOS__ -#define __MSDOS__ -#endif -#elif defined(__OS2__) -#ifndef __OS2__ /* TODO: to be completed */ -#define __OS2__ -#define __OS2_32__ /* Default to 32 bit OS/2 */ -#endif -#else -#define __UNIX__ /* TODO: to be completed */ -#endif - -/* We have the following defines to define the calling conventions for - * publicly accesible functions: - * - * _PUBAPI - Compiler default calling conventions for all public 'C' functions - * _ASMAPI - Calling conventions for all public assembler functions - * _DLLAPI - Calling conventions for all DLL exported functions - * _DLLVAR - Modifier to export/import globals in 32 bit DLL's - * _EXPORT - Expands to _export when compiling a DLL - * _VARAPI - Modifiers for variables; Watcom C++ mangles C++ globals - */ - -#define _PUBAPI -#define _ASMAPI __cdecl - -#if defined(_MSC_VER) && defined(_WIN32) && !defined(__SC__) -#define __PASCAL __stdcall -#define __export -#define __import -#else -#define __PASCAL __pascal -#endif - -#if defined(__WATCOMC__) -#define _VARAPI __cdecl -#else -#define _VARAPI -#endif - -#if defined(__WINDOWS__) -#ifdef BUILD_DLL -#define _DLLASM __export __cdecl -#define _EXPORT __export -#ifdef __WINDOWS32__ -#define _DLLAPI __export __PASCAL -#define _DLLVAR __export -#else -#define _DLLAPI __export __far __pascal -#define _DLLVAR -#endif -#else -#define _DLLASM __cdecl -#define _EXPORT -#ifdef __WINDOWS32__ -#define _DLLAPI __PASCAL -#define _DLLVAR __import -#else -#define _DLLAPI __far __pascal -#define _DLLVAR -#endif -#endif -#else -#define _EXPORT -#define _DLLAPI -#define _DLLVAR -#endif - -/* Useful macros */ - -#define PRIVATE static -#define PUBLIC - -#ifdef DEBUG -# define DBG(x) x -#else -# define DBG(x) -#endif - -#ifndef NULL -# define NULL 0L -#endif - -#ifndef MAX -# define MAX(a,b) ( ((a) > (b)) ? (a) : (b)) -#endif -#ifndef MIN -# define MIN(a,b) ( ((a) < (b)) ? (a) : (b)) -#endif -#ifndef ABS -# define ABS(a) ((a) >= 0 ? (a) : -(a)) -#endif -#ifndef SIGN -# define SIGN(a) ((a) > 0 ? 1 : -1) -#endif - -/* General typedefs */ - -#ifndef __GENDEFS -#define __GENDEFS -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef int ibool; /* Integer boolean type */ -#ifndef __cplusplus -#define bool ibool /* Standard C */ -#else -#ifndef __HAS_BOOL__ -#define bool ibool /* Older C++ compilers */ -#endif -#endif /* __cplusplus */ -#endif /* __GENDEFS */ - -/* Includes Windows headers, as they define TRUE and FALSE */ - -#ifdef __WINDOWS__ -#ifndef _WINDOWS_ /* Dont include if already included */ -#ifndef __WIN386__ -#define STRICT -#define WIN32_LEAN_AND_MEAN -#endif -#include -#endif -#endif - -/* Boolean truth values */ - -#undef false -#undef true -#undef NO -#undef YES -#undef FALSE -#undef TRUE - -#ifdef __cplusplus /* Cast to bool's for C++ code */ -#define false ((bool)0) -#define true ((bool)1) -#define NO ((bool)0) -#define YES ((bool)1) -#define FALSE ((bool)0) -#define TRUE ((bool)1) -#else /* Define to 0 and 1 for C code */ -#define false 0 -#define true 1 -#define NO 0 -#define YES 1 -#define FALSE 0 -#define TRUE 1 -#endif - -#endif /* __DEBUG_H */ +/**************************************************************************** +* +* Copyright (C) 1996 SciTech Software +* All rights reserved. +* +* Filename: $Workfile: debug.h $ +* Version: $Revision: 1.17 $ +* +* Language: ANSI C +* Environment: any +* +* Description: General header file for operating system portable code. +* +* $Date: 04 Mar 1997 11:34:08 $ $Author: KendallB $ +* +****************************************************************************/ + +#ifndef __DEBUG_H +#define __DEBUG_H + +/* We have the following defines to identify the compilation environment: + * + * __16BIT__ Compiling for 16 bit code (any environment) + * __32BIT__ Compiling for 32 bit code (any environment) + * __MSDOS__ Compiling for MS-DOS (includes __WINDOWS16__, __WIN386__) + * __REALDOS__ Compiling for MS-DOS (excludes __WINDOWS16__) + * __MSDOS16__ Compiling for 16 bit MS-DOS + * __MSDOS32__ Compiling for 32 bit MS-DOS + * __WINDOWS__ Compiling for Windows + * __WINDOWS16__ Compiling for 16 bit Windows (__MSDOS__ also defined) + * __WINDOWS32__ Compiling for 32 bit Windows + * __WIN386__ Compiling for Watcom C++ Win386 extended Windows + * __OS2__ Compiling for OS/2 + * __OS2_16__ Compiling for 16 bit OS/2 + * __OS2_32__ Compiling for 32 bit OS/2 + * __UNIX__ Compiling for Unix + * + */ + +#ifdef __SC__ +#if __INTSIZE == 4 +#define __SC386__ +#endif +#endif + +#ifdef __GNUC__ +#define __cdecl /* GCC doesn't know about __cdecl modifiers */ +#define __FLAT__ /* GCC is always 32 bit flat model */ +#define __HAS_BOOL__ /* Latest GNU C++ has bool type */ +#endif + +#ifdef __BORLANDC__ +#if (__BORLANDC__ >= 0x500) || defined(CLASSLIB_DEFS_H) +#define __HAS_BOOL__ /* Borland C++ 5.0 and later define bool type */ +#endif +#endif + +/* For the Metaware High C/C++ compiler, there is no _cdecl calling + * convention. The conventions can be changed, but it is a complicated + * process involving #pragmas, and all externally referenced functions + * will use stack based calling conventions. We also need to change the + * global aliasing conventions to use underscores for external function + * and variables names, so that our assembler routines will link + * correctly (except of course the main function - man what a PAIN!). + */ + +#ifdef __HIGHC__ +#define __cdecl +#define __FLAT__ /* High C is always 32 bit flat model */ +#pragma Global_aliasing_convention("_%r") +extern main(); +#pragma Alias(main,"main") +#endif + +#if defined(__MSDOS__) || defined(__DOS__) || defined(__DPMI32__) || (defined(M_I86) && !defined(__SC386__)) +#ifndef __MSDOS__ +#define __MSDOS__ +#endif +#if defined(__386__) || defined(__FLAT__) || defined(__NT__) || defined(__SC386__) +#ifndef __MSDOS32__ +#define __MSDOS32__ +#endif +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __REALDOS__ +#define __REALDOS__ +#endif +#elif (defined(_Windows) || defined(_WINDOWS)) && !defined(__DPMI16__) +#ifndef __16BIT__ +#define __16BIT__ +#endif +#ifndef __WINDOWS16__ +#define __WINDOWS16__ +#endif +#ifndef __WINDOWS__ +#define __WINDOWS__ +#endif +#ifndef __MSDOS__ +#define __MSDOS__ +#endif +#else +#ifndef __16BIT__ +#define __16BIT__ +#endif +#ifndef __MSDOS16__ +#define __MSDOS16__ +#endif +#ifndef __REALDOS__ +#define __REALDOS__ +#endif +#endif +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __WINDOWS32__ +#define __WINDOWS32__ +#endif +#ifndef _WIN32 +#define _WIN32 /* Microsoft Win32 SDK headers use _WIN32 */ +#endif +#ifndef WIN32 +#define WIN32 /* OpenGL headers use WIN32 */ +#endif +#ifndef __WINDOWS__ +#define __WINDOWS__ +#endif +#elif defined(__WINDOWS_386__) +#ifndef __32BIT__ +#define __32BIT__ +#endif +#ifndef __WIN386__ +#define __WIN386__ +#endif +#ifndef __WINDOWS__ +#define __WINDOWS__ +#endif +#ifndef __MSDOS__ +#define __MSDOS__ +#endif +#elif defined(__OS2__) +#ifndef __OS2__ /* TODO: to be completed */ +#define __OS2__ +#define __OS2_32__ /* Default to 32 bit OS/2 */ +#endif +#else +#define __UNIX__ /* TODO: to be completed */ +#endif + +/* We have the following defines to define the calling conventions for + * publicly accesible functions: + * + * _PUBAPI - Compiler default calling conventions for all public 'C' functions + * _ASMAPI - Calling conventions for all public assembler functions + * _DLLAPI - Calling conventions for all DLL exported functions + * _DLLVAR - Modifier to export/import globals in 32 bit DLL's + * _EXPORT - Expands to _export when compiling a DLL + * _VARAPI - Modifiers for variables; Watcom C++ mangles C++ globals + */ + +#define _PUBAPI +#define _ASMAPI __cdecl + +#if defined(_MSC_VER) && defined(_WIN32) && !defined(__SC__) +#define __PASCAL __stdcall +#define __export +#define __import +#else +#define __PASCAL __pascal +#endif + +#if defined(__WATCOMC__) +#define _VARAPI __cdecl +#else +#define _VARAPI +#endif + +#if defined(__WINDOWS__) +#ifdef BUILD_DLL +#define _DLLASM __export __cdecl +#define _EXPORT __export +#ifdef __WINDOWS32__ +#define _DLLAPI __export __PASCAL +#define _DLLVAR __export +#else +#define _DLLAPI __export __far __pascal +#define _DLLVAR +#endif +#else +#define _DLLASM __cdecl +#define _EXPORT +#ifdef __WINDOWS32__ +#define _DLLAPI __PASCAL +#define _DLLVAR __import +#else +#define _DLLAPI __far __pascal +#define _DLLVAR +#endif +#endif +#else +#define _EXPORT +#define _DLLAPI +#define _DLLVAR +#endif + +/* Useful macros */ + +#define PRIVATE static +#define PUBLIC + +#ifdef DEBUG +# define DBG(x) x +#else +# define DBG(x) +#endif + +#ifndef NULL +# define NULL 0L +#endif + +#ifndef MAX +# define MAX(a,b) ( ((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a,b) ( ((a) < (b)) ? (a) : (b)) +#endif +#ifndef ABS +# define ABS(a) ((a) >= 0 ? (a) : -(a)) +#endif +#ifndef SIGN +# define SIGN(a) ((a) > 0 ? 1 : -1) +#endif + +/* General typedefs */ + +#ifndef __GENDEFS +#define __GENDEFS +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef int ibool; /* Integer boolean type */ +#ifndef __cplusplus +#define bool ibool /* Standard C */ +#else +#ifndef __HAS_BOOL__ +#define bool ibool /* Older C++ compilers */ +#endif +#endif /* __cplusplus */ +#endif /* __GENDEFS */ + +/* Includes Windows headers, as they define TRUE and FALSE */ + +#ifdef __WINDOWS__ +#ifndef _WINDOWS_ /* Dont include if already included */ +#ifndef __WIN386__ +#define STRICT +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif +#endif + +/* Boolean truth values */ + +#undef false +#undef true +#undef NO +#undef YES +#undef FALSE +#undef TRUE + +#ifdef __cplusplus /* Cast to bool's for C++ code */ +#define false ((bool)0) +#define true ((bool)1) +#define NO ((bool)0) +#define YES ((bool)1) +#define FALSE ((bool)0) +#define TRUE ((bool)1) +#else /* Define to 0 and 1 for C code */ +#define false 0 +#define true 1 +#define NO 0 +#define YES 1 +#define FALSE 0 +#define TRUE 1 +#endif + +#endif /* __DEBUG_H */ diff --git a/WinQuake/scitech/INCLUDE/MGLDOS.H b/WinQuake/scitech/INCLUDE/MGLDOS.H index aa286c0..a852760 100644 --- a/WinQuake/scitech/INCLUDE/MGLDOS.H +++ b/WinQuake/scitech/INCLUDE/MGLDOS.H @@ -1,83 +1,83 @@ -/**************************************************************************** -* -* MegaGraph Graphics Library -* -* Copyright (C) 1996 SciTech Software. -* All rights reserved. -* -* Filename: $Workfile: mgldos.h $ -* Version: $Revision: 1.9 $ -* -* Language: ANSI C -* Environment: IBM PC (MS DOS) -* -* Description: Header file for the MGLDOS binding for the MSDOS environment. -* -* $Date: 30 Jan 1997 17:31:58 $ $Author: KendallB $ -* -****************************************************************************/ - -#ifndef __MGLDOS_H -#define __MGLDOS_H - -#ifndef MGLDOS -#define MGLDOS -#endif - -/*---------------------- Macros and type definitions ----------------------*/ - -typedef void *MGL_HWND; - -/*------------------------- Function Prototypes ---------------------------*/ - -#ifdef __cplusplus -extern "C" { /* Use "C" linkage when in C++ mode */ -#endif - -/* Initialise the MGL for fullscreen output */ - -bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath); - -/* Change the active display mode. You must destroy all display device - * contexts before calling this function, and re-create them again with - * the new display mode. Does not affect any event handling hooks. - */ - -bool MGLAPI MGL_changeDisplayMode(m_int mode); - -/* Disable/enable event handling (call before calling MGL_init */ - -void MGLAPI MGL_useEvents(bool use); - -/* Device context management */ - -MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers); -MGLDC * MGLAPI MGL_createScrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers); -MGLDC * MGLAPI MGL_createOffscreenDC(void); -MGLDC * MGLAPI MGL_createLinearOffscreenDC(void); -MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf); -bool MGLAPI MGL_destroyDC(MGLDC *dc); - -/* Generic helper functions */ - -ulong MGLAPI MGL_getTicks(void); -ulong MGLAPI MGL_getTickResolution(void); -void MGLAPI MGL_delay(m_int millseconds); -void MGLAPI MGL_beep(m_int freq,m_int milliseconds); -void MGLAPI MGL_suspend(void); -void MGLAPI MGL_resume(void); - -/* Fullscreen specific routines */ - -void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level); -m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc); - -/* Determine if a specific scancode'ed key is held down (PC specific) */ - -bool MGLAPI EVT_isKeyDown(uchar scanCode); - -#ifdef __cplusplus -} /* End of "C" linkage for C++ */ -#endif - -#endif /* __MGLDOS_H */ +/**************************************************************************** +* +* MegaGraph Graphics Library +* +* Copyright (C) 1996 SciTech Software. +* All rights reserved. +* +* Filename: $Workfile: mgldos.h $ +* Version: $Revision: 1.9 $ +* +* Language: ANSI C +* Environment: IBM PC (MS DOS) +* +* Description: Header file for the MGLDOS binding for the MSDOS environment. +* +* $Date: 30 Jan 1997 17:31:58 $ $Author: KendallB $ +* +****************************************************************************/ + +#ifndef __MGLDOS_H +#define __MGLDOS_H + +#ifndef MGLDOS +#define MGLDOS +#endif + +/*---------------------- Macros and type definitions ----------------------*/ + +typedef void *MGL_HWND; + +/*------------------------- Function Prototypes ---------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Initialise the MGL for fullscreen output */ + +bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath); + +/* Change the active display mode. You must destroy all display device + * contexts before calling this function, and re-create them again with + * the new display mode. Does not affect any event handling hooks. + */ + +bool MGLAPI MGL_changeDisplayMode(m_int mode); + +/* Disable/enable event handling (call before calling MGL_init */ + +void MGLAPI MGL_useEvents(bool use); + +/* Device context management */ + +MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers); +MGLDC * MGLAPI MGL_createScrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers); +MGLDC * MGLAPI MGL_createOffscreenDC(void); +MGLDC * MGLAPI MGL_createLinearOffscreenDC(void); +MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf); +bool MGLAPI MGL_destroyDC(MGLDC *dc); + +/* Generic helper functions */ + +ulong MGLAPI MGL_getTicks(void); +ulong MGLAPI MGL_getTickResolution(void); +void MGLAPI MGL_delay(m_int millseconds); +void MGLAPI MGL_beep(m_int freq,m_int milliseconds); +void MGLAPI MGL_suspend(void); +void MGLAPI MGL_resume(void); + +/* Fullscreen specific routines */ + +void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level); +m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc); + +/* Determine if a specific scancode'ed key is held down (PC specific) */ + +bool MGLAPI EVT_isKeyDown(uchar scanCode); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __MGLDOS_H */ diff --git a/WinQuake/scitech/INCLUDE/MGLWIN.H b/WinQuake/scitech/INCLUDE/MGLWIN.H index c5b9c30..6cb9c9e 100644 --- a/WinQuake/scitech/INCLUDE/MGLWIN.H +++ b/WinQuake/scitech/INCLUDE/MGLWIN.H @@ -1,152 +1,152 @@ -/**************************************************************************** -* -* MegaGraph Graphics Library -* -* Copyright (C) 1996 SciTech Software. -* All rights reserved. -* -* Filename: $Workfile: mglwin.h $ -* Version: $Revision: 1.14 $ -* -* Language: ANSI C -* Environment: IBM PC (MS DOS) -* -* Description: Header file for the MGLWIN bindings for MS Windows using -* WinG in a window and WinDirect for full screen. The MGLWIN -* binding only targets Win32 applications, so cannot be used -* for 16 bit Windows development. -* -* $Date: 14 Mar 1997 16:09:34 $ $Author: KendallB $ -* -****************************************************************************/ - -#ifndef __MGLWIN_H -#define __MGLWIN_H - -#ifndef MGLWIN -#define MGLWIN -#endif - -/*---------------------- Macros and type definitions ----------------------*/ - -typedef HWND MGL_HWND; -typedef HDC MGL_HDC; -typedef HINSTANCE MGL_HINSTANCE; - -/*------------------------- Function Prototypes ---------------------------*/ - -#ifdef __cplusplus -extern "C" { /* Use "C" linkage when in C++ mode */ -#endif - -/* Initialise the MGL for fullscreen output */ - -bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath); - -/* Initialise the MGL just for Windowed output, not full screen */ - -bool MGLAPI MGL_initWindowed(const char *mglpath); - -/* Function to register a fullscreen window with the MGL. If you wish - * for the MGL to use your own window for fullscreen modes, you can - * register it with this function. Note that when the MGL goes into - * fullscreen modes, the attributes, size and position of the window are - * modified to make it into a fullscreen Window necessary to cover the - * entire desktop, and the state of the window will be restore to the original - * format on return to normal GDI mode. - * - * Note that if you are using a common window for Windowed mode and fullscreen - * modes of your application, you will need to ensure that certain messages - * that you window normally handles in windowed modes are ignored when in - * fullscreen modes. - */ - -void MGLAPI MGL_registerFullScreenWindow(HWND hwndFullScreen); - -/* Function to register a fullscreen event handling window procedure. - * If you wish to do your own event handling, you can register your window - * procedure with the MGL using this function and it will be called - * when there are messages to be handled. You can still call the MGL_event() - * functions even if you have registered an event handling procedure. - */ - -void MGLAPI MGL_registerEventProc(WNDPROC userWndProc); - -/* Change the active display mode. You must destroy all display device - * contexts before calling this function, and re-create them again with - * the new display mode. Does not affect any event handling hooks. - */ - -bool MGLAPI MGL_changeDisplayMode(m_int mode); - -/* Obtain the handle to the MGL fullscreen window when in fullscreen modes */ - -MGL_HWND MGLAPI MGL_getFullScreenWindow(void); - -/* Tell the MGL what your applications main window is */ - -void MGLAPI MGL_setMainWindow(MGL_HWND hwnd); - -/* Tell the MGL your applications instance handle (call before all funcs!) */ - -void MGLAPI MGL_setAppInstance(MGL_HINSTANCE hInstApp); - -/* Device context management */ - -MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers); -MGLDC * MGLAPI MGL_createSrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers); -MGLDC * MGLAPI MGL_createOffscreenDC(void); -MGLDC * MGLAPI MGL_createLinearOffscreenDC(void); -MGLDC * MGLAPI MGL_createWindowedDC(MGL_HWND hwnd); -MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf); -bool MGLAPI MGL_destroyDC(MGLDC *dc); - -/* Get a Windows HDC for the MGL device context. You can use this returned - * HDC to get GDI to draw to the device context surface, such as rendering - * and using TrueType fonts with the MGL. If a Windows compatible HDC is not - * available, this function will return NULL. - */ - -HDC MGLAPI MGL_getWinDC(MGLDC *dc); - -/* Associate a Window manager DC with the MGLDC for painting */ - -bool MGLAPI MGL_setWinDC(MGLDC *dc,MGL_HDC hdc); - -/* Activate the WindowDC's palette */ - -bool MGLAPI MGL_activatePalette(MGLDC *dc,bool unrealize); - -/* Let the MGL know when your application is being activated or deactivated. - * This function only needs to be called when running in Windowed modes and - * you have set the system palette to SYSPAL_NOSTATIC mode, to ensure - * that the MGL can properly re-map your application palette when your - * app is not active and allow Windows to re-map your bitmap colors on the - * fly. This function should be passed a pointer to the currently active - * MGL Windowed DC and a flag to indicate whether the app is in the background - * or not. - */ - -void MGLAPI MGL_appActivate(MGLDC *winDC,bool active); - -/* Generic helper functions */ - -ulong MGLAPI MGL_getTicks(void); -ulong MGLAPI MGL_getTickResolution(void); -void MGLAPI MGL_delay(m_int millseconds); -void MGLAPI MGL_beep(m_int freq,m_int milliseconds); - -/* Fullscreen specific routines */ - -void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level); -m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc); - -/* Determine if a specific scancode'ed key is held down (PC specific) */ - -bool MGLAPI EVT_isKeyDown(uchar scanCode); - -#ifdef __cplusplus -} /* End of "C" linkage for C++ */ -#endif - -#endif /* __MGLWIN_H */ +/**************************************************************************** +* +* MegaGraph Graphics Library +* +* Copyright (C) 1996 SciTech Software. +* All rights reserved. +* +* Filename: $Workfile: mglwin.h $ +* Version: $Revision: 1.14 $ +* +* Language: ANSI C +* Environment: IBM PC (MS DOS) +* +* Description: Header file for the MGLWIN bindings for MS Windows using +* WinG in a window and WinDirect for full screen. The MGLWIN +* binding only targets Win32 applications, so cannot be used +* for 16 bit Windows development. +* +* $Date: 14 Mar 1997 16:09:34 $ $Author: KendallB $ +* +****************************************************************************/ + +#ifndef __MGLWIN_H +#define __MGLWIN_H + +#ifndef MGLWIN +#define MGLWIN +#endif + +/*---------------------- Macros and type definitions ----------------------*/ + +typedef HWND MGL_HWND; +typedef HDC MGL_HDC; +typedef HINSTANCE MGL_HINSTANCE; + +/*------------------------- Function Prototypes ---------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Initialise the MGL for fullscreen output */ + +bool MGLAPI MGL_init(m_int *driver,m_int *mode,const char *mglpath); + +/* Initialise the MGL just for Windowed output, not full screen */ + +bool MGLAPI MGL_initWindowed(const char *mglpath); + +/* Function to register a fullscreen window with the MGL. If you wish + * for the MGL to use your own window for fullscreen modes, you can + * register it with this function. Note that when the MGL goes into + * fullscreen modes, the attributes, size and position of the window are + * modified to make it into a fullscreen Window necessary to cover the + * entire desktop, and the state of the window will be restore to the original + * format on return to normal GDI mode. + * + * Note that if you are using a common window for Windowed mode and fullscreen + * modes of your application, you will need to ensure that certain messages + * that you window normally handles in windowed modes are ignored when in + * fullscreen modes. + */ + +void MGLAPI MGL_registerFullScreenWindow(HWND hwndFullScreen); + +/* Function to register a fullscreen event handling window procedure. + * If you wish to do your own event handling, you can register your window + * procedure with the MGL using this function and it will be called + * when there are messages to be handled. You can still call the MGL_event() + * functions even if you have registered an event handling procedure. + */ + +void MGLAPI MGL_registerEventProc(WNDPROC userWndProc); + +/* Change the active display mode. You must destroy all display device + * contexts before calling this function, and re-create them again with + * the new display mode. Does not affect any event handling hooks. + */ + +bool MGLAPI MGL_changeDisplayMode(m_int mode); + +/* Obtain the handle to the MGL fullscreen window when in fullscreen modes */ + +MGL_HWND MGLAPI MGL_getFullScreenWindow(void); + +/* Tell the MGL what your applications main window is */ + +void MGLAPI MGL_setMainWindow(MGL_HWND hwnd); + +/* Tell the MGL your applications instance handle (call before all funcs!) */ + +void MGLAPI MGL_setAppInstance(MGL_HINSTANCE hInstApp); + +/* Device context management */ + +MGLDC * MGLAPI MGL_createDisplayDC(m_int numBuffers); +MGLDC * MGLAPI MGL_createSrollingDC(m_int virtualX,m_int virtualY,m_int numBuffers); +MGLDC * MGLAPI MGL_createOffscreenDC(void); +MGLDC * MGLAPI MGL_createLinearOffscreenDC(void); +MGLDC * MGLAPI MGL_createWindowedDC(MGL_HWND hwnd); +MGLDC * MGLAPI MGL_createMemoryDC(m_int xSize,m_int ySize,m_int bitsPerPixel,pixel_format_t *pf); +bool MGLAPI MGL_destroyDC(MGLDC *dc); + +/* Get a Windows HDC for the MGL device context. You can use this returned + * HDC to get GDI to draw to the device context surface, such as rendering + * and using TrueType fonts with the MGL. If a Windows compatible HDC is not + * available, this function will return NULL. + */ + +HDC MGLAPI MGL_getWinDC(MGLDC *dc); + +/* Associate a Window manager DC with the MGLDC for painting */ + +bool MGLAPI MGL_setWinDC(MGLDC *dc,MGL_HDC hdc); + +/* Activate the WindowDC's palette */ + +bool MGLAPI MGL_activatePalette(MGLDC *dc,bool unrealize); + +/* Let the MGL know when your application is being activated or deactivated. + * This function only needs to be called when running in Windowed modes and + * you have set the system palette to SYSPAL_NOSTATIC mode, to ensure + * that the MGL can properly re-map your application palette when your + * app is not active and allow Windows to re-map your bitmap colors on the + * fly. This function should be passed a pointer to the currently active + * MGL Windowed DC and a flag to indicate whether the app is in the background + * or not. + */ + +void MGLAPI MGL_appActivate(MGLDC *winDC,bool active); + +/* Generic helper functions */ + +ulong MGLAPI MGL_getTicks(void); +ulong MGLAPI MGL_getTickResolution(void); +void MGLAPI MGL_delay(m_int millseconds); +void MGLAPI MGL_beep(m_int freq,m_int milliseconds); + +/* Fullscreen specific routines */ + +void MGLAPI MGL_setPaletteSnowLevel(MGLDC *dc,m_int level); +m_int MGLAPI MGL_getPaletteSnowLevel(MGLDC *dc); + +/* Determine if a specific scancode'ed key is held down (PC specific) */ + +bool MGLAPI EVT_isKeyDown(uchar scanCode); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __MGLWIN_H */ diff --git a/WinQuake/scitech/INCLUDE/MGRAPH.H b/WinQuake/scitech/INCLUDE/MGRAPH.H index 1b72f3f..fe00a8e 100644 --- a/WinQuake/scitech/INCLUDE/MGRAPH.H +++ b/WinQuake/scitech/INCLUDE/MGRAPH.H @@ -1,1951 +1,1951 @@ -/**************************************************************************** -* -* MegaGraph Graphics Library -* -* Copyright (C) 1996 SciTech Software. -* All rights reserved. -* -* Filename: $Workfile: mgraph.h $ -* Version: $Revision: 1.29 $ -* -* Language: ANSI C -* Environment: IBM PC (MS DOS) -* -* Description: Header file for the MegaGraph Graphics Library. You can -* defined one of the following to specify which MGL API you -* wish to use. -* -* MGL_LITE - Compile for the MGL/Lite API -* MGL_PRO - Compile for the MGL/Pro API -* MGL_FIX3D - Compile for the MGL/3D API (fixed point) -* MGL_FLT3D - Compile for the MGL/3D API (floating point) -* -* If you do not define any of these, MGL_FIX3D will be defined -* automatically for compatibility with older versions of the -* MGL. -* -* $Date: 11 Mar 1997 16:46:42 $ $Author: KendallB $ -* -****************************************************************************/ - -#ifndef __MGRAPH_H -#define __MGRAPH_H - -#include - -#ifndef __DEBUG_H -#include "debug.h" -#endif - -#if !defined(MGL_LITE) && !defined(MGL_PRO) && !defined(MGL_FIX3D) \ - && !defined(MGL_FLT3D) -#define MGL_FIX3D -#endif - -#if defined(MGL_FIX3D) || defined(MGL_FLT3D) -#define MGL_3D -#endif - -/*---------------------- Macros and type definitions ----------------------*/ - -#pragma pack(1) /* Pack structures to byte granularity */ - -/* Define the version number for the MGL release */ - -#define MGL_VERSION_STR "3.1" - -/* Define the calling conventions for all public MGL functions. If we - * are compiling the MGL as a DLL, then all public functions are compiled - * and exported with standard C calling conventions, otherwise we use - * the default calling conventions provided by the compiler. - * - * Note that because Watcom C++ uses register based parameter passing - * by default we also provide special DLL's for watcom that are compiled - * with register parameter passing. This is necessary to work with all - * the extra libraries provided as they are all compiled to call MGL - * functions with arguments in registers whenever possible. You can still - * use the standard DLL but if you do you will need to re-compile all - * of the extra libraries with the MGL_DLL #define to change the calling - * conventions for the MGL functions. - */ - -#if defined(MGL_DLL) -#define MGLAPI _EXPORT __cdecl -#else -#define MGLAPI _EXPORT _PUBAPI -#endif -#define ASMAPI _EXPORT __cdecl - -/* Define a type for integers used in the library. For most environments - * we simply define it as a normal integer (16 or 32 bits), however for - * 16 bit Windows it is defined as a 32 bit integer as all the real code - * lives in a 32 bit DLL that uses 32 bit integers. - */ - -#ifndef __M_INT_DEFINED -#if defined(__WINDOWS16__) -typedef long m_int; -typedef unsigned long m_uint; -#else -typedef int m_int; -typedef unsigned int m_uint; -#endif -#define __M_INT_DEFINED -#endif - -/* Define the graphics subsystems available */ - -typedef enum { - grDETECT = -1, /* Auto detect the graphics subsystem */ - grNONE = 0, /* No graphics hardware detected */ - grVGA, /* Standard VGA */ - grVESA, /* VESA VBE compliant SuperVGA */ - grSVGA, /* Unaccelerated SuperVGA */ - grACCEL, /* Accelerated SuperVGA */ - grDDRAW, /* Unaccelerated DirectDraw */ - grDDRAWACCEL, /* Accelerated DirectDraw */ - grDDRAW3D, /* 3D Accelerated DirectDraw */ - grMAXDRIVER, /* Maximum driver number */ - } MGL_driverType; - -/* Graphics modes supported - the only video modes supported by this - * graphics library are those that support at least 16 colors per pixel. - */ - -typedef enum { - /* 16 color VGA video modes */ - - grVGA_320x200x16, - grVGA_640x200x16, - grVGA_640x350x16, - grVGA_640x400x16, - grVGA_640x480x16, - grSVGA_800x600x16, - - /* 256 color VGA ModeX video modes */ - - grVGAX_320x200x256, - grVGAX_320x240x256, - grVGAX_320x400x256, - grVGAX_320x480x256, - - /* 256 color VGA video modes */ - - grVGA_320x200x256, - - /* 256 color VGA/SuperVGA video modes */ - - grSVGA_320x200x256, - grSVGA_320x240x256, - grSVGA_320x400x256, - grSVGA_320x480x256, - grSVGA_400x300x256, - grSVGA_512x384x256, - grSVGA_640x350x256, - grSVGA_640x400x256, - grSVGA_640x480x256, - grSVGA_800x600x256, - grSVGA_1024x768x256, - grSVGA_1152x864x256, - grSVGA_1280x960x256, - grSVGA_1280x1024x256, - grSVGA_1600x1200x256, - - /* 32,768 color Super VGA video modes */ - - grSVGA_320x200x32k, - grSVGA_320x240x32k, - grSVGA_320x400x32k, - grSVGA_320x480x32k, - grSVGA_400x300x32k, - grSVGA_512x384x32k, - grSVGA_640x350x32k, - grSVGA_640x400x32k, - grSVGA_640x480x32k, - grSVGA_800x600x32k, - grSVGA_1024x768x32k, - grSVGA_1152x864x32k, - grSVGA_1280x960x32k, - grSVGA_1280x1024x32k, - grSVGA_1600x1200x32k, - - /* 65,536 color Super VGA video modes */ - - grSVGA_320x200x64k, - grSVGA_320x240x64k, - grSVGA_320x400x64k, - grSVGA_320x480x64k, - grSVGA_400x300x64k, - grSVGA_512x384x64k, - grSVGA_640x350x64k, - grSVGA_640x400x64k, - grSVGA_640x480x64k, - grSVGA_800x600x64k, - grSVGA_1024x768x64k, - grSVGA_1152x864x64k, - grSVGA_1280x960x64k, - grSVGA_1280x1024x64k, - grSVGA_1600x1200x64k, - - /* 16 million color, 24 bits per pixel Super VGA video modes */ - - grSVGA_320x200x16m, - grSVGA_320x240x16m, - grSVGA_320x400x16m, - grSVGA_320x480x16m, - grSVGA_400x300x16m, - grSVGA_512x384x16m, - grSVGA_640x350x16m, - grSVGA_640x400x16m, - grSVGA_640x480x16m, - grSVGA_800x600x16m, - grSVGA_1024x768x16m, - grSVGA_1152x864x16m, - grSVGA_1280x960x16m, - grSVGA_1280x1024x16m, - grSVGA_1600x1200x16m, - - /* 16 million color, 32 bits per pixel Super VGA video modes */ - - grSVGA_320x200x4G, - grSVGA_320x240x4G, - grSVGA_320x400x4G, - grSVGA_320x480x4G, - grSVGA_400x300x4G, - grSVGA_512x384x4G, - grSVGA_640x350x4G, - grSVGA_640x400x4G, - grSVGA_640x480x4G, - grSVGA_800x600x4G, - grSVGA_1024x768x4G, - grSVGA_1152x864x4G, - grSVGA_1280x960x4G, - grSVGA_1280x1024x4G, - grSVGA_1600x1200x4G, - - /* Render into Windowing System DC (Windows, OS/2 PM, X11) */ - - grWINDOWED, - - grMAXMODE, /* Maximum mode number */ - } MGL_modeType; - -/* MGL_result() error codes */ - -typedef enum { - grOK = 0, /* No error */ - grNoInit = -1, /* Graphics driver has not been installed */ - grNotDetected = -2, /* Graphics hardware was not detected */ - grDriverNotFound= -3, /* Graphics driver file not found */ - grBadDriver = -4, /* File loaded was not a graphics driver */ - grLoadMem = -5, /* Not enough memory to load graphics driver*/ - grInvalidMode = -6, /* Invalid graphics mode for selected driver*/ - grError = -8, /* General graphics error */ - grInvalidName = -9, /* Invalid driver name */ - grNoMem = -10, /* Not enough memory to perform operation */ - grNoModeSupport = -11, /* Select video mode not supported by hard. */ - grInvalidFont = -12, /* Invalid font data */ - grBadFontFile = -13, /* File loaded was not a font file */ - grFontNotFound = -14, /* Font file was not found */ - grOldDriver = -15, /* Driver file is an old version */ - grInvalidDevice = -16, /* Invalid device for selected operation */ - grInvalidDC = -17, /* Invalid device context */ - grInvalidCursor = -18, /* Invalid cursor file */ - grCursorNotFound= -19, /* Cursor file was not found */ - grInvalidIcon = -20, /* Invalid icon file */ - grIconNotFound = -21, /* Icon file was not found */ - grInvalidBitmap = -22, /* Invalid bitmap file */ - grBitmapNotFound= -23, /* Bitmap file was not found */ - grZbufferTooBig = -24, /* Zbuffer allocation is too large */ - grNewFontFile = -25, /* Only Windows 2.x font files supported */ - grNoDoubleBuff = -26, /* Double buffering is not available */ - grNoHardwareBlt = -28, /* No hardware bitBlt for OffscreenDC */ - grNoOffscreenMem= -29, /* No available offscreen memory */ - grInvalidPF = -30, /* Invalid pixel format for memory DC */ - - grLastError = -31, /* Last error number in list */ - } MGL_errorType; - -#define MGL_CLIPON true -#define MGL_CLIPOFF false - -/* Color mapped modes */ - -typedef enum { - MGL_CMAP_MODE, /* Normal Color mapped mode */ - MGL_DITHER_RGB_MODE, /* 24 bit RGB halftone dithered */ - } MGL_colorModes; - -/* Standard colors - this is the standard set of colors for the IBM PC. The - * default palette will have been programmed to contain these values when a - * graphics modes is started. If the palette has been changed, they will - * not correspond to the actual colors on the screen. Under a Windowing - * manage environment these colors will also not be setup by default. - */ - -enum MGL_COLORS { - MGL_BLACK, /* dark colors */ - MGL_BLUE, - MGL_GREEN, - MGL_CYAN, - MGL_RED, - MGL_MAGENTA, - MGL_BROWN, - MGL_LIGHTGRAY, - MGL_DARKGRAY, /* light colors */ - MGL_LIGHTBLUE, - MGL_LIGHTGREEN, - MGL_LIGHTCYAN, - MGL_LIGHTRED, - MGL_LIGHTMAGENTA, - MGL_YELLOW, - MGL_WHITE, - }; - -/* Windows standard color indices for 256 color bitmaps. 8,9,246,247 are - * reserved and you should not count on these colors always being the - * same. For 16 color bitmaps, colors 248-255 map to colors 8-15. - */ - -enum MGL_WIN_COLORS { - MGL_WIN_BLACK = 0, - MGL_WIN_DARKRED = 1, - MGL_WIN_DARKGREEN = 2, - MGL_WIN_DARKYELLOW = 3, - MGL_WIN_DARKBLUE = 4, - MGL_WIN_DARKMAGENTA = 5, - MGL_WIN_DARKCYAN = 6, - MGL_WIN_LIGHTGRAY = 7, - MGL_WIN_TURQUOISE = 8, /* Reserved; dont count on this */ - MGL_WIN_SKYBLUE = 9, /* Reserved; dont count on this */ - MGL_WIN_CREAM = 246, /* Reserved; dont count on this */ - MGL_WIN_MEDIUMGRAY = 247, /* Reserved; dont count on this */ - MGL_WIN_DARKGRAY = 248, - MGL_WIN_LIGHTRED = 249, - MGL_WIN_LIGHTGREEN = 250, - MGL_WIN_LIGHTYELLOW = 251, - MGL_WIN_LIGHTBLUE = 252, - MGL_WIN_LIGHTMAGENTA = 253, - MGL_WIN_LIGHTCYAN = 254, - MGL_WIN_WHITE = 255, - }; - -typedef enum { - MGL_MARKER_SQUARE, - MGL_MARKER_CIRCLE, - MGL_MARKER_X, - } MGL_markerStyleType; - -typedef enum { /* Write mode operators */ - MGL_REPLACE_MODE, /* Replace mode */ - MGL_AND_MODE, /* AND mode */ - MGL_OR_MODE, /* OR mode */ - MGL_XOR_MODE, /* XOR mode */ - } MGL_writeModeType; - -typedef enum { - MGL_BITMAP_SOLID, - MGL_BITMAP_OPAQUE, - MGL_BITMAP_TRANSPARENT, - MGL_PIXMAP, - } MGL_fillStyleType; - -typedef enum { - MGL_LINE_PENSTYLE, /* Line drawn in current pen style */ - MGL_LINE_STIPPLE, /* Line drawn with current stipple */ - } MGL_lineStyleType; - -typedef enum { - MGL_CONVEX_POLYGON, /* Monotone vertical polygon */ - MGL_COMPLEX_POLYGON, /* Non-Simple polygons */ - MGL_AUTO_POLYGON, /* Auto detect the polygon type */ - } MGL_polygonType; - -/* Text manipulation defines */ - -typedef enum { - MGL_LEFT_TEXT = 0, /* Justify from left */ - MGL_TOP_TEXT = 0, /* Justify from top */ - MGL_CENTER_TEXT = 1, /* Center the text */ - MGL_RIGHT_TEXT = 2, /* Justify from right */ - MGL_BOTTOM_TEXT = 2, /* Justify from bottom */ - MGL_BASELINE_TEXT = 3, /* Justify from the baseline */ - } MGL_textJustType; - -typedef enum { - MGL_LEFT_DIR = 0, /* Text goes to left */ - MGL_UP_DIR = 1, /* Text goes up */ - MGL_RIGHT_DIR = 2, /* Text goes right */ - MGL_DOWN_DIR = 3, /* Text goes down */ - } MGL_textDirType; - -/* Font types */ - -typedef enum { - MGL_VECTORFONT = 1, /* Vector font */ - MGL_FIXEDFONT, /* Fixed width bitmap font */ - MGL_PROPFONT, /* Proportional width bitmap font */ - } MGL_fontType; - -/* Palette rotation directions */ - -typedef enum { - MGL_ROTATE_UP, /* Rotate the palette values up */ - MGL_ROTATE_DOWN, /* Rotate the palette values down */ - } MGL_palRotateType; - -/* Border drawing routine styles */ - -typedef enum { - MGL_BDR_INSET, /* Interior is inset into screen */ - MGL_BDR_OUTSET, /* Interior is outset from screen */ - MGL_BDR_OUTLINE, /* Border is 3d outline */ - } MGL_bdrStyleType; - -/* Standard display driver names */ - -#define MGL_VGA4NAME "VGA4.DRV" /* Standard VGA drivers */ -#define MGL_VGA8NAME "VGA8.DRV" -#define MGL_VGAXNAME "VGAX.DRV" - -#define MGL_SVGA4NAME "SVGA4.DRV" /* Generic SuperVGA drivers */ -#define MGL_SVGA8NAME "SVGA8.DRV" -#define MGL_SVGA16NAME "SVGA16.DRV" -#define MGL_SVGA24NAME "SVGA24.DRV" -#define MGL_SVGA32NAME "SVGA32.DRV" - -#define MGL_LINEAR8NAME "LINEAR8.DRV" /* Linear framebuffer drivers */ -#define MGL_LINEAR16NAME "LINEAR16.DRV" -#define MGL_LINEAR24NAME "LINEAR24.DRV" -#define MGL_LINEAR32NAME "LINEAR32.DRV" - -#define MGL_ACCEL8NAME "ACCEL8.DRV" /* VBE/AF Accelerated drivers */ -#define MGL_ACCEL16NAME "ACCEL16.DRV" -#define MGL_ACCEL24NAME "ACCEL24.DRV" -#define MGL_ACCEL32NAME "ACCEL32.DRV" - -#define MGL_DDRAW8NAME "DDRAW8.DRV" /* DirectDraw drivers */ -#define MGL_DDRAW16NAME "DDRAW16.DRV" -#define MGL_DDRAW24NAME "DDRAW24.DRV" -#define MGL_DDRAW32NAME "DDRAW32.DRV" - -/* Standard memory driver names */ - -#define MGL_PACKED1NAME "PACK1.DRV" -#define MGL_PACKED4NAME "PACK4.DRV" -#define MGL_PACKED8NAME "PACK8.DRV" -#define MGL_PACKED16NAME "PACK16.DRV" -#define MGL_PACKED24NAME "PACK24.DRV" -#define MGL_PACKED32NAME "PACK32.DRV" - -/* Standard bitmap names */ - -#define MGL_EMPTY_FILL _MGL_getEmptyPat() -#define MGL_GRAY_FILL _MGL_getGrayPat() -#define MGL_SOLID_FILL _MGL_getSolidPat() - -/* Event message masks for keyDown events */ - -#define EVT_ASCIIMASK 0x00FF /* Ascii code of key pressed */ -#define EVT_SCANMASK 0xFF00 /* Scan code of key pressed */ -#define EVT_COUNTMASK 0x7FFF0000L /* Count for KEYREPEAT's */ - -#define EVT_asciiCode(m) ( (uchar) (m & EVT_ASCIIMASK) ) -#define EVT_scanCode(m) ( (uchar) ( (m & EVT_SCANMASK) >> 8 ) ) -#define EVT_repeatCount(m) ( (short) ( (m & EVT_COUNTMASK) >> 16 ) ) - -/* Event message masks for mouse events */ - -#define EVT_LEFTBMASK 0x0001 /* Left button is bit 0 */ -#define EVT_RIGHTBMASK 0x0004 /* Right button is bit 1 */ -#define EVT_BOTHBMASK 0x0005 /* Both left and right together */ -#define EVT_ALLBMASK 0x0005 /* All buttons pressed */ - -/* Modifier masks */ - -#define EVT_LEFTBUT 0x0001 /* Set if left button was down */ -#define EVT_RIGHTBUT 0x0002 /* Set if right button was down */ -#define EVT_RIGHTSHIFT 0x0008 /* Set if right shift down */ -#define EVT_LEFTSHIFT 0x0010 /* Set if left shift down */ -#define EVT_CTRLSTATE 0x0020 /* Set if ctrl key down */ -#define EVT_ALTSTATE 0x0040 /* Set if alt key down */ -#define EVT_LEFTCTRL 0x0080 /* Set if left ctrl key down */ -#define EVT_LEFTALT 0x0100 /* Set if left alt key down */ -#define EVT_SHIFTKEY 0x0018 /* Any shift key */ - -/* Event codes */ - -#define EVT_NULLEVT 0x0000 /* A null event */ -#define EVT_KEYDOWN 0x0001 /* Key down event */ -#define EVT_KEYREPEAT 0x0002 /* Key repeat event */ -#define EVT_KEYUP 0x0004 /* Key up event */ -#define EVT_MOUSEDOWN 0x0008 /* Mouse down event */ -#define EVT_MOUSEUP 0x0010 /* Mouse up event */ -#define EVT_MOUSEMOVE 0x0020 /* Mouse movement event */ -#define EVT_TIMERTICK 0x0040 /* Timer tick event */ -#define EVT_USEREVT 0x0080 /* First user event */ - -/* Event code masks */ - -#define EVT_KEYEVT (EVT_KEYDOWN | EVT_KEYREPEAT | EVT_KEYUP) -#define EVT_MOUSEEVT (EVT_MOUSEDOWN | EVT_MOUSEUP | EVT_MOUSEMOVE) -#define EVT_MOUSECLICK (EVT_MOUSEDOWN | EVT_MOUSEUP) -#define EVT_EVERYEVT 0xFFFF - -/* Suspend Application callback type codes. This callback is called - * when the user presses one of the corresponding keys indicating that - * they wish to change the active application. The MGL will catch these - * events and if you have registered a callback, will call the callback to - * save the state of the application so that it can be properly restored - * when the user switches back to your application. The MGL takes care of - * all the details about saving and restoring the state of the hardware, - * and all your application needs to do is save its own state so that you can - * re-draw the application screen upon re-activation. - * - * NOTE: Your application suspend callback may get called twice with the - * MGL_DEACTIVATE flag in order to test whether the switch should - * occur (under both DirectDraw and WinDirect fullscreen modes). - * - * NOTE: When your callback is called with the MGL_DEACTIVATE flag, you - * cannot assume that you have access to the display memory surfaces - * as they may have been lost by the time your callback has been called. - */ - -#define MGL_DEACTIVATE 0x0001 /* Application losing active focus */ -#define MGL_REACTIVATE 0x0002 /* Application regaining active focus */ - -/* Return codes from the suspend application callback. The normal value - * to be returned is MGL_SUSPEND_APP and this will cause the app to be - * suspended while back in GDI mode until the app is re-activated again - * by the user. - * - * MGL_NO_DEACTIVATE signals to WinDirect that the application does not want - * to allow switching to occur, and the switch request will be ignored and - * the app will remain in fullscreen mode. - * - * MGL_NO_SUSPEND_APP can be used to tell WinDirect to switch back to the - * desktop, but not to suspend the application. This must be used with - * care as the suspend application callback is then responsible for setting - * a flag in the application that will stop the application from doing any - * rendering to the framebuffer while the application is in GDI mode. This - * return value is useful for games that need to maintain network - * connectivity while the user has temporarily switched back to GDI mode. - */ - -#define MGL_NO_DEACTIVATE 0 /* Dont allow app to be deactivated */ -#define MGL_SUSPEND_APP 1 /* Suspend application until restored */ -#define MGL_NO_SUSPEND_APP 2 /* Dont suspend, but allow switch */ - -/* Here we define the structures used to represent points and rectangles */ - -typedef struct { - m_int x,y; - } point_t; - -typedef struct { - m_int left; - m_int top; - m_int right; - m_int bottom; - } rect_t; - -/* All colors are represented as longs by the library. This allows - * code to work correctly with up to 24 bit color device drivers. The - * device drivers themselves expect the color to be a color index if in - * a color mapped mode, or a 15/16/24 bit RGB tuple in a hicolor or truecolor - * mode. You can use the appropriate routines to pack and unpack - * colors into the color_t format. - */ - -typedef ulong color_t; - -/* Define the value used to clear the software ZBuffer. The MGL always uses - * a > operator for the z compare, and the smallest value is 0. - */ - -#define MGL_ZCLEARVAL 0 - -/* Structures for passing vertex information to polygon rendering routines. - * All fixed point coordinates are passed in 16.16 signed fixed point - * format, while zbuffer coordinates are passed in 4.28 signed fixed point - * format. The sign bit is used purely for overflow and arithmetic - * internally, and all user passed zbuffer values should be greater than - * 0. All shaded rendering routines either take a color index in 8.16 fixed - * point format (range 0-255.9) or separate RGB components in 8.16 fixed - * point format (range 0-255.9). - */ - -#ifdef __FX_FIXED_H -#define fix32_t FXFixed -#else -typedef long fix32_t; -#endif -typedef fix32_t fxcolor_t; -typedef long zfix32_t; - -typedef struct { - fix32_t x,y; - } fxpoint_t; - -typedef struct { - fxcolor_t r,g,b; - } fxrgb_t; - -typedef struct { - fix32_t w,s,t; - } fxtex_t; - -typedef struct { - fxcolor_t c; - fxpoint_t p; - } fxpointc_t; - -typedef struct { - fxrgb_t c; - fxpoint_t p; - } fxpointrgb_t; - -typedef struct { - fxpoint_t p; - zfix32_t z; - } fxpointz_t; - -typedef struct { - fxcolor_t c; - fxpoint_t p; - zfix32_t z; - } fxpointcz_t; - -typedef struct { - fxrgb_t c; - fxpoint_t p; - zfix32_t z; - } fxpointrgbz_t; - -/* Macros to convert between integer and 32 bit fixed point format */ - -#define MGL_FIX_1 0x10000L -#define MGL_FIX_2 0x20000L -#define MGL_FIX_HALF 0x08000L -#define MGL_TOFIX(i) ((long)(i) << 16) -#define MGL_FIXTOINT(f) ((m_int)((f) >> 16)) -#define MGL_FIXROUND(f) ((m_int)(((f) + MGL_FIX_HALF) >> 16)) - -#define MGL_ZFIX_1 0x10000000L -#define MGL_ZFIX_HALF 0x08000000L -#define MGL_FIXTOZ(i) ((i) << 12) -#define MGL_ZTOFIX(i) ((i) >> 12) -#define MGL_TOZFIX(i) ((long)(i) << 28) -#define MGL_ZFIXTOINT(f) ((m_int)((f) >> 28)) -#define MGL_ZFIXROUND(f) ((m_int)(((f) + MGL_ZFIX_HALF) >> 28)) - -/* Region structure */ - -#ifdef BUILD_MGL -struct _span_t; -typedef struct _span_t span_t; -#else -typedef void span_t; -#endif - -typedef struct { - rect_t rect; /* Bounding rectangle for region */ - span_t *spans; /* Start of span list for region */ - } region_t; - -/* Palette entry structure */ - -typedef struct { - uchar blue; /* Blue component of color */ - uchar green; /* Green component of color */ - uchar red; /* Blue component of color */ - uchar alpha; /* Alpha or alignment byte */ - } palette_t; - -/* Maximum value for each palette entry component */ - -#define PALMAX 255 /* Max value for palette components */ - -/* Pixel format structure */ - -typedef struct { - uchar redMask,greenMask; /* Mask values for pixels */ - uchar blueMask,rsvdMask; - m_int redPos,redAdjust; /* Red position and adjustment */ - m_int greenPos,greenAdjust; /* Green position and adjustment */ - m_int bluePos,blueAdjust; /* Blue position and adjustment */ - m_int rsvdPos,rsvdAdjust; /* Reserved position and adjustment */ - } pixel_format_t; - -/* Structure to hold arc coordinate information */ - -typedef struct { - m_int x,y; /* Centre point of the arc */ - m_int startX,startY; /* Starting point on arc */ - m_int endX,endY; /* Ending point on arc */ - } arc_coords_t; - -/* Mouse cursor structure */ - -typedef struct { - ulong xorMask[32]; - ulong andMask[32]; - m_int xHotSpot; - m_int yHotSpot; - } cursor_t; - -/* Bitmap structure - always packed pixel DIB format */ - -typedef struct { - m_int width; /* Width of bitmap in pixels */ - m_int height; /* Height of bitmap in pixels */ - m_int bitsPerPixel; /* Pixel width */ - m_int bytesPerLine; /* Bytes per line value for surface */ - uchar *surface; /* Pointer to bitmap surface */ - palette_t *pal; /* Palette (NULL if not loaded) */ - pixel_format_t *pf; /* Pixel format (NULL if none) */ - - /* ... palette, pixel format and bitmap data are store contiguously */ - } bitmap_t; - -/* Icon structure - can be 32x23, 64x64 or in fact any size */ - -typedef struct { - m_int byteWidth; /* Byte with for AND mask */ - uchar *andMask; /* Hold punch mask for icon */ - bitmap_t xorMask; /* XOR mask for the icon */ - - /* ... AND mask and bitmap structure are stored contiguously */ - } icon_t; - -/* Default cursor name */ - -#define MGL_DEF_CURSOR _MGL_getDefCursor() - -/* Generic Font structure */ - -#define _MGL_FNAMESIZE 58 - -typedef struct { - char name[_MGL_FNAMESIZE];/* Name of the font */ - short fontType; /* Type of font */ - short maxWidth; /* Maximum character width */ - short maxKern; /* Maximum character kern */ - short fontWidth; /* Font width */ - short fontHeight; /* Font height */ - short ascent; /* Font ascent value */ - short descent; /* Font descent value */ - short leading; /* Font leading value */ - } font_t; - -/* Character and font metrics structure */ - -typedef struct { - m_int width; /* Width of character or font */ - m_int fontWidth; /* Character width (tightest fit) */ - m_int fontHeight; /* Height of the font */ - m_int ascent; /* Ascent value */ - m_int descent; /* Descent value */ - m_int leading; /* Leading value */ - m_int kern; /* Kern value */ - } metrics_t; - -/* Text settings structure */ - -typedef struct { - m_int horizJust; /* Horizontal justfication */ - m_int vertJust; /* Vertical justification */ - m_int dir; /* Text drawing direction */ - m_int szNumerx; /* Text x size numerator */ - m_int szNumery; /* Text y size numerator */ - m_int szDenomx; /* Text x size denominator */ - m_int szDenomy; /* Text y size denominator */ - m_int spaceExtra; /* Space extra term */ - font_t *font; /* Currently selected font */ - } text_settings_t; - -/* Macros to access the (left,top) and (right,bottom) points of a - * rectangle. - */ - -#define MGL_leftTop(r) (((point_t *) &(r))[0]) -#define MGL_rightBottom(r) (((point_t *) &(r))[1]) - -typedef uchar pattern_t[8]; -typedef color_t pixpattern_t[8][8]; - -/* Attributes structure */ - -typedef struct { - color_t color; /* Foreground color */ - color_t backColor; /* Background color */ - m_int colorMode; /* Current color mode */ - m_int markerSize; /* Size of markers in pixels */ - m_int markerStyle; /* Style of markers */ - color_t markerColor; /* Color to draw markers in */ - color_t bdrBright; /* Border bright color */ - color_t bdrDark; /* Border dark color */ - point_t CP; /* Graphics pen position */ - m_int writeMode; /* Scan conversion write mode op. */ - m_int penStyle; /* Pen style */ - m_int penHeight; /* Height of pen */ - m_int penWidth; /* Width of pen */ - pattern_t penPat; /* Pattern for pen */ - pixpattern_t penPixPat; /* Pixmap pattern for pen */ - m_int lineStyle; /* Line style */ - ushort lineStipple; /* Line stipple */ - m_uint stippleCount; /* Current line stipple count */ - rect_t viewPort; /* Viewport dimensions */ - point_t viewPortOrg; /* Logical viewport origin */ - rect_t clipRect; /* Clipping rectangle dimensions */ - m_int clip; /* Is clipping on? */ - m_int polyType; /* Polygon drawing type */ - text_settings_t ts; /* Text drawing attributes */ - } attributes_t; - -/* Mode specific format information. This structrure can be used by - * the device driver to build tables of values for all supported modes - */ - -typedef struct { - m_int xRes; /* Device x resolution - 1 */ - m_int yRes; /* Device y resolution - 1 */ - m_int bitsPerPixel; /* Number of bits per pixel */ - m_int numberOfPlanes; /* Number of planes in image */ - color_t maxColor; /* Maximum number of colors - 1 */ - m_int maxPage; /* Maximum number of video pages - 1 */ - m_int bytesPerLine; /* Number of bytes in a line */ - m_int aspectRatio; /* Mode aspect ratio (horiz/vert * 1000) */ - long pageSize; /* Number of bytes in a page */ - m_int scratch1; /* Scratch pad value 1 */ - m_int scratch2; /* Scratch pad value 2 */ - char redMaskSize; /* Size of direct color red mask */ - char redFieldPosition; /* Bit posn of lsb of red mask */ - char greenMaskSize; /* Size of direct color green mask */ - char greenFieldPosition; /* Bit posn of lsb of green mask */ - char blueMaskSize; /* Size of direct color blue mask */ - char blueFieldPosition; /* Bit posn of lsb of blue mask */ - char rsvdMaskSize; /* Size of reserved mask */ - char rsvdFieldPosition; /* Bit posn of reserved mask */ - } gmode_t; - -/* Public Device Context Structure. The 'surface' member along with the - * gmode_t information block, provides direct access to the active - * display surface for user applications. The MGL virtualises the surface - * in SuperVGA modes that dont have a real linear framebuffer. - */ - -typedef struct { - attributes_t a; /* Active device attributes */ - void *surface; /* Pointer to active device surface */ - void *zbuffer; /* Pointer to Z-buffer if allocated */ - m_int zbits; /* Bits per zbuffer element */ - m_int zwidth; /* Width of the zbuffer in pixels */ - gmode_t mi; /* Mode specific information block */ - pixel_format_t pf; /* Current pixel format for device context */ - color_t *colorTab; /* Color lookup table cache */ - color_t *shadeTab; /* Currently active shade table */ - m_int bankOffset; /* Offset of starting bank number */ - - /* Remainder of Device Context structure is private and internal */ - } publicDevCtx_t; - -#ifndef BUILD_MGL -typedef publicDevCtx_t MGLDC; -#else -struct internalDevCtx_t; -typedef struct internalDevCtx_t MGLDC; -#endif - -typedef struct { - ulong which; /* Which window for window manager code */ - m_uint what; /* Event code */ - ulong when; /* Clock ticks since midnight */ - m_int where_x; /* Mouse location */ - m_int where_y; - ulong message; /* Event specific message */ - ulong modifiers; /* Modifier flags */ - m_int next; /* Next event in queue */ - m_int prev; /* Previous event in queue */ - } event_t; - -/* Structure containing file I/O functions allowing the user application to - * completely replace the MGL's file I/O functions with their own. This - * allows the app to store all MGL related files in a single large file, - * with encryption or compression is desired. By default normal file I/O - * functions will be used. - */ - -typedef struct { - FILE * (*fopen)(const char *filename,const char *mode); - int (*fclose)(FILE *f); - int (*fseek)(FILE *f,long offset,int whence); - long (*ftell)(FILE *f); - size_t (*fread)(void *ptr,size_t size,size_t n,FILE *f); - size_t (*fwrite)(const void *ptr,size_t size,size_t n,FILE *f); - } fileio_t; - -/* Define the flags for the types of direct surface access provided */ - -#define MGL_NO_ACCESS 0x0 /* Surface cannot be accessed */ -#define MGL_VIRTUAL_ACCESS 0x1 /* Surface is virtualised */ -#define MGL_LINEAR_ACCESS 0x2 /* Surface can be linearly accessed */ -#define MGL_SURFACE_FLAGS 0x3 - -/* Define the flags for the types of direct zbuffer access provided */ - -#define MGL_NO_ZACCESS 0x0 /* Zbuffer cannot be accessed */ -#define MGL_VIRTUAL_ZACCESS 0x4 /* Zbuffer is virtualised in */ -#define MGL_LINEAR_ZACCESS 0x8 /* Zbuffer can be linearly accessed */ -#define MGL_ZBUFFER_FLAGS 0xC - -/* Define the flags for the types of hardware acceleration supported by - * the device context. This will allow the application to tailor the use of - * MGL functions depending upon whether specific hardware support is - * available. Hence applications can use specialised software rendering - * support if the desired hardware support is not available. - * - * NOTE: If the hardware flags are not MGL_HW_NONE, you *must* call - * the MGL_beginDirectAccess() and MGL_endDirectAccess() functions - * before and after any custom code that does direct framebuffer - * rendering!! - * - * This is not necessary for non-accelerated device context, so you - * might want to optimise these calls out if there is no hardware - * acceleration support. - */ - -#define MGL_HW_NONE 0x0000 /* No hardware acceleration */ -#define MGL_HW_LINE 0x0010 /* Hardware line drawing */ -#define MGL_HW_STIPPLE_LINE 0x0020 /* Hardware stippled line drawing */ -#define MGL_HW_POLY 0x0040 /* Hardware polygon filling */ -#define MGL_HW_RECT 0x0080 /* Hardware rectangle fill */ -#define MGL_HW_PATT_RECT 0x0100 /* Hardware pattern rectangle fill */ -#define MGL_HW_CLRPATT_RECT 0x0200 /* Hardware color pattern fill */ -#define MGL_HW_SCR_BLT 0x0400 /* Hardware screen/screen bitBlt */ -#define MGL_HW_SRCTRANS_BLT 0x0800 /* Hardware source transparent blt */ -#define MGL_HW_DSTTRANS_BLT 0x1000 /* Hardware dest. transparent blt */ -#define MGL_HW_MONO_BLT 0x2000 /* Hardware monochrome blt */ -#define MGL_HW_CLIP 0x4000 /* Hardware clipping */ -#define MGL_HW_FLAGS 0xFFF0 - -#ifdef __cplusplus -extern "C" { /* Use "C" linkage when in C++ mode */ -#endif - -/*------------------------- Function Prototypes ---------------------------*/ - -/*--------------------------------------------------------------------------- - * Routines bound to a specific device context. These routines all take - * an MGLDC as a parmeter for the context to work with and hence dont work - * with the current context. If however the context passed is the currently - * active context, all changes to that context are reflected in the - * currently active context as well. - *-------------------------------------------------------------------------*/ - -/* Environment detection and initialisation */ - -m_int MGLAPI MGL_registerDriver(const char *name,void *driver); -void MGLAPI MGL_unregisterAllDrivers(void); -void MGLAPI MGL_registerAllDispDrivers(bool useLinear,bool useDirectDraw,bool useWinDirect); -void MGLAPI MGL_registerAllMemDrivers(void); -void MGLAPI MGL_detectGraph(m_int *driver,m_int *mode); -uchar * MGLAPI MGL_availableModes(void); -m_int MGLAPI MGL_availablePages(m_int mode); -m_int MGLAPI MGL_modeResolution(m_int mode,m_int *xRes,m_int *yRes,m_int *bitsPerPixel); -bool MGLAPI MGL_isDisplayDC(MGLDC *dc); -bool MGLAPI MGL_isWindowedDC(MGLDC *dc); -bool MGLAPI MGL_isMemoryDC(MGLDC *dc); -void MGLAPI MGL_exit(void); -void MGLAPI MGL_setBufSize(unsigned size); -void MGLAPI MGL_fatalError(const char *msg); -m_int MGLAPI MGL_result(void); -void MGLAPI MGL_setResult(m_int result); -const char * MGLAPI MGL_errorMsg(m_int err); -const char * MGLAPI MGL_modeName(m_int mode); -const char * MGLAPI MGL_modeDriverName(m_int mode); -const char * MGLAPI MGL_driverName(m_int driver); -m_int MGLAPI MGL_getDriver(MGLDC *dc); -m_int MGLAPI MGL_getMode(MGLDC *dc); -m_int MGLAPI MGL_surfaceAccessType(MGLDC *dc); -m_int MGLAPI MGL_zbufferAccessType(MGLDC *dc); -long MGLAPI MGL_getHardwareFlags(MGLDC *dc); -void MGLAPI MGL_defaultAttributes(MGLDC *dc); -void MGLAPI MGL_makeSubDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom); - -/* Viewport and clip rectangle manipulation bound to a specific DC */ - -void MGLAPI MGL_setViewportDC(MGLDC *dc,rect_t view); -void MGLAPI MGL_setRelViewportDC(MGLDC *dc,rect_t view); -void MGLAPI MGL_getViewportDC(MGLDC *dc,rect_t *view); -void MGLAPI MGL_setViewportOrgDC(MGLDC *dc,point_t org); -void MGLAPI MGL_getViewportOrgDC(MGLDC *dc,point_t *org); -void MGLAPI MGL_globalToLocalDC(MGLDC *dc,point_t *p); -void MGLAPI MGL_localToGlobalDC(MGLDC *dc,point_t *p); -m_int MGLAPI MGL_maxxDC(MGLDC *dc); -m_int MGLAPI MGL_maxyDC(MGLDC *dc); -void MGLAPI MGL_setClipRectDC(MGLDC *dc,rect_t clip); -void MGLAPI MGL_getClipRectDC(MGLDC *dc,rect_t *clip); -void MGLAPI MGL_setClipModeDC(MGLDC *dc,bool mode); -bool MGLAPI MGL_getClipModeDC(MGLDC *dc); - -/* Color and palette manipulation */ - -color_t MGLAPI MGL_realColor(MGLDC *dc,m_int color); -color_t MGLAPI MGL_rgbColor(MGLDC *dc,uchar R,uchar G,uchar B); -void MGLAPI MGL_setPaletteEntry(MGLDC *dc,m_int entry,uchar red,uchar green,uchar blue); -void MGLAPI MGL_getPaletteEntry(MGLDC *dc,m_int entry,uchar *red,uchar *green,uchar *blue); -void MGLAPI MGL_setPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex); -void MGLAPI MGL_getPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex); -void ASMAPI MGL_rotatePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int direction); -bool ASMAPI MGL_fadePalette(MGLDC *dc,palette_t *fullIntensity,m_int numColors,m_int startIndex,uchar intensity); -void MGLAPI MGL_realizePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int waitVRT); -m_int MGLAPI MGL_getPaletteSize(MGLDC *dc); -void MGLAPI MGL_getDefaultPalette(MGLDC *dc,palette_t *pal); -void MGLAPI MGL_setDefaultPalette(MGLDC *dc); -#ifndef MGL_LITE -bool MGLAPI MGL_checkIdentityPalette(bool enable); -void MGLAPI MGL_mapToPalette(MGLDC *dc,palette_t *pal); -#endif - -/* Generic device context information and manipulation */ - -bool MGLAPI MGL_haveWidePalette(MGLDC *dc); -m_int MGLAPI MGL_getBitsPerPixel(MGLDC *dc); -color_t MGLAPI MGL_maxColor(MGLDC *dc); -m_int MGLAPI MGL_maxPage(MGLDC *dc); -m_int MGLAPI MGL_sizex(MGLDC *dc); -m_int MGLAPI MGL_sizey(MGLDC *dc); -void MGLAPI MGL_getPixelFormat(MGLDC *dc,pixel_format_t *pf); -void * MGLAPI MGL_computePixelAddr(MGLDC *dc,int x,int y); - -/* Double buffering support */ - -void MGLAPI MGL_setActivePage(MGLDC *dc,m_int page); -m_int MGLAPI MGL_getActivePage(MGLDC *dc); -void MGLAPI MGL_setVisualPage(MGLDC *dc,m_int page,m_int waitVRT); -m_int MGLAPI MGL_getVisualPage(MGLDC *dc); -void MGLAPI MGL_setDisplayStart(MGLDC *dc,m_int x,m_int y,m_int waitFlag); -void MGLAPI MGL_getDisplayStart(MGLDC *dc,m_int *x,m_int *y); -void MGLAPI MGL_vSync(MGLDC *dc); -bool MGLAPI MGL_doubleBuffer(MGLDC *dc); -void MGLAPI MGL_singleBuffer(MGLDC *dc); -void MGLAPI MGL_swapBuffers(MGLDC *dc,m_int waitVRT); - -/* Zbuffering support */ - -#ifdef MGL_3D -m_int MGLAPI MGL_getHardwareZBufferDepth(MGLDC *dc); -bool ASMAPI MGL_zBegin(MGLDC *dc,m_int zbits); -bool MGLAPI MGL_zShareZBuffer(MGLDC *dc,MGLDC *dcShared,m_int zbits); -#endif - -/* Event handling support */ - -bool MGLAPI EVT_getNext(event_t *evt,m_uint mask); -bool MGLAPI EVT_peekNext(event_t *evt,m_uint mask); -bool MGLAPI EVT_post(ulong which,m_uint what,ulong message,ulong modifiers); -void MGLAPI EVT_flush(m_uint mask); -void MGLAPI EVT_halt(event_t *evt,m_uint mask); -m_int MGLAPI EVT_setTimerTick(m_int ticks); - -/*--------------------------------------------------------------------------- - * Routines bound to the currently active context. All these routines work - * with the currently active context and do not reflect any changes made - * to the global context to the original user supplied context (because it - * may be cached). The cached DC is automatically flushed back to the - * original DC when a new context is enabled with MGL_makeCurrentDC(). - * - * Before destroying a DC that is current, make sure you call - * MGL_makeCurrentDC(NULL) first! - *-------------------------------------------------------------------------*/ - -/* Routines to change the active global device context */ - -MGLDC * MGLAPI MGL_makeCurrentDC(MGLDC *dc); -bool MGLAPI MGL_isCurrentDC(MGLDC *dc); - -/* Current device context information and manipulation */ - -m_int MGLAPI MGL_getAspectRatio(void); -void MGLAPI MGL_setAspectRatio(m_int aspectRatio); -void ASMAPI MGL_setColor(color_t color); -void MGLAPI MGL_setColorRGB(uchar R,uchar G,uchar B); -void MGLAPI MGL_setColorCI(m_int index); -color_t MGLAPI MGL_getColor(void); -void ASMAPI MGL_setBackColor(color_t color); -color_t MGLAPI MGL_getBackColor(void); -color_t ASMAPI MGL_packColor(pixel_format_t *pf,uchar R,uchar G,uchar B); -void MGLAPI MGL_unpackColor(pixel_format_t *pf,color_t color,uchar *R,uchar *G,uchar *B); -color_t ASMAPI MGL_packColorRGB(uchar R,uchar G,uchar B); -void MGLAPI MGL_unpackColorRGB(color_t color,uchar *R,uchar *G,uchar *B); -color_t MGLAPI MGL_defaultColor(void); -#ifndef MGL_LITE -void MGLAPI MGL_setMarkerSize(m_int size); -m_int MGLAPI MGL_getMarkerSize(void); -void MGLAPI MGL_setMarkerStyle(m_int style); -m_int MGLAPI MGL_getMarkerStyle(void); -void MGLAPI MGL_setMarkerColor(color_t color); -color_t MGLAPI MGL_getMarkerColor(void); -void MGLAPI MGL_setBorderColors(color_t bright,color_t dark); -void MGLAPI MGL_getBorderColors(color_t *bright,color_t *dark); -void ASMAPI MGL_setWriteMode(m_int mode); -m_int MGLAPI MGL_getWriteMode(void); -void ASMAPI MGL_setPenStyle(m_int style); -m_int MGLAPI MGL_getPenStyle(void); -void MGLAPI MGL_setLineStyle(m_int style); -m_int MGLAPI MGL_getLineStyle(void); -void ASMAPI MGL_setLineStipple(ushort stipple); -ushort MGLAPI MGL_getLineStipple(void); -void ASMAPI MGL_setLineStippleCount(m_uint stippleCount); -m_uint MGLAPI MGL_getLineStippleCount(void); -void ASMAPI MGL_setPenBitmapPattern(const pattern_t *pat); -void MGLAPI MGL_getPenBitmapPattern(pattern_t *pat); -void ASMAPI MGL_setPenPixmapPattern(const pixpattern_t *pat); -void MGLAPI MGL_getPenPixmapPattern(pixpattern_t *pat); -void MGLAPI MGL_setPenSize(m_int height,m_int width); -void MGLAPI MGL_getPenSize(m_int *height,m_int *width); -#ifndef MGL_LITE -void MGLAPI MGL_setColorMapMode(m_int mode); -m_int MGLAPI MGL_getColorMapMode(void); -#endif -void MGLAPI MGL_setPolygonType(m_int type); -m_int MGLAPI MGL_getPolygonType(void); -#endif -void MGLAPI MGL_getAttributes(attributes_t *attr); -void MGLAPI MGL_restoreAttributes(attributes_t *attr); - -/* Device clearing */ - -void ASMAPI MGL_clearDevice(void); -void MGLAPI MGL_clearViewport(void); - -/* Viewport and clip rectangle manipulation */ - -void MGLAPI MGL_setViewport(rect_t view); -void MGLAPI MGL_setRelViewport(rect_t view); -void MGLAPI MGL_getViewport(rect_t *view); -void MGLAPI MGL_setViewportOrg(point_t org); -void MGLAPI MGL_getViewportOrg(point_t *org); -void MGLAPI MGL_globalToLocal(point_t *p); -void MGLAPI MGL_localToGlobal(point_t *p); -m_int MGLAPI MGL_maxx(void); -m_int MGLAPI MGL_maxy(void); -void MGLAPI MGL_setClipRect(rect_t clip); -void MGLAPI MGL_getClipRect(rect_t *clip); -void MGLAPI MGL_setClipMode(bool mode); -bool MGLAPI MGL_getClipMode(void); - -/* Pixel plotting */ - -void MGLAPI MGL_pixelCoord(m_int x,m_int y); -color_t MGLAPI MGL_getPixelCoord(m_int x,m_int y); -void ASMAPI MGL_beginPixel(void); -void MGLAPI MGL_pixelCoordFast(m_int x,m_int y); -color_t MGLAPI MGL_getPixelCoordFast(m_int x,m_int y); -void ASMAPI MGL_endPixel(void); - -/* Line drawing and clipping */ - -void MGLAPI MGL_moveToCoord(m_int x,m_int y); -void MGLAPI MGL_moveRelCoord(m_int dx,m_int dy); -void MGLAPI MGL_lineToCoord(m_int x,m_int y); -void MGLAPI MGL_lineRelCoord(m_int dx,m_int dy); -m_int MGLAPI MGL_getX(void); -m_int MGLAPI MGL_getY(void); -void MGLAPI MGL_getCP(point_t* CP); -void MGLAPI MGL_lineCoord(m_int x1,m_int y1,m_int x2,m_int y2); -void MGLAPI MGL_lineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2); -void MGLAPI MGL_lineCoordFast(m_int x1,m_int y1,m_int x2,m_int y2); -void MGLAPI MGL_lineCoordFastFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2); -void MGLAPI MGL_lineEngine(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,void (ASMAPI *plotPoint)(m_int x,m_int y)); -bool MGLAPI MGL_clipLineFX(fix32_t *x1,fix32_t *y1,fix32_t *x2,fix32_t *y2,fix32_t left,fix32_t top,fix32_t right,fix32_t bottom); -#ifndef MGL_LITE -void ASMAPI MGL_scanLine(m_int y,m_int x1,m_int x2); -#endif - -/* Routines to perform bank switching for banked framebuffers for custom - * rendering code. The first version is callable only from assembler and - * requires the new bank value to be passed in the DL register. The second - * version is callable directly from C. DO NOT CALL THESE FUNCTIONS WHEN - * RUNNING WITH A LINEAR FRAMEBUFFER!!! - */ - -void _ASMAPI SVGA_setBank(void); -void _ASMAPI SVGA_setBankC(int bank); - -/* Routines to begin/end direct framebuffer access. You must call these - * functions is you wish to render directly to a hardware accelerated - * device surface. - */ - -void ASMAPI MGL_beginDirectAccess(void); -void ASMAPI MGL_endDirectAccess(void); - -/* Routines to begin/end fast rendering of flat shaded lines, scanlines - * and polygons. - */ - -void ASMAPI MGL_beginDrawing(void); -void ASMAPI MGL_endDrawing(void); - -/* Routines to begin/end fast rendering of smooth shaded lines, scanlines - * and polygons. - */ - -#ifdef MGL_3D -void ASMAPI MGL_beginShadedDrawing(void); -void ASMAPI MGL_endShadedDrawing(void); -#endif - -/* Routines to begin/end fast rendering of flat shaded, zbuffered lines and - * polygons. - */ - -#ifdef MGL_3D -void ASMAPI MGL_beginZDrawing(void); -void ASMAPI MGL_endZDrawing(void); -#endif - -/* Routines to begin/end fast rendering of smooth shaded, zbuffered lines and - * polygons. - */ - -#ifdef MGL_3D -void ASMAPI MGL_beginZShadedDrawing(void); -void ASMAPI MGL_endZShadedDrawing(void); -#endif - -/* Polygon drawing: Note that the following fast polygon routines - * only work with convex polygons. The integer coordinate versions are - * provided for compatibility only, and convert the coordinates to fixed - * point and call the appropriate fixed point routines below. - */ - -#ifndef MGL_LITE -void MGLAPI MGL_fillPolygon(m_int count,point_t *vArray,m_int xOffset,m_int yOffset); -void MGLAPI MGL_fillPolygonFast(m_int count,point_t *vArray,m_int xOffset,m_int yOffset); -void ASMAPI MGL_fillPolygonFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_fillPolygonFastFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset); -#endif - -/* 3D rasterization routines */ - -#ifdef MGL_3D -void MGLAPI MGL_zClearCoord(m_int left,m_int top,m_int right,m_int bottom,zfix32_t clearVal); -#endif - -#ifdef MGL_FIX3D -void ASMAPI MGL_cLineCoordFast(fix32_t x1,fix32_t y1,fix32_t c1,fix32_t x2,fix32_t y2,fix32_t c2); -void ASMAPI MGL_rgbLineCoordFast(fix32_t x1,fix32_t y1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,fix32_t r2,fix32_t g2,fix32_t b2); -void ASMAPI MGL_zLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t x2,fix32_t y2,zfix32_t z2); -void ASMAPI MGL_czLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t c1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t c2); -void ASMAPI MGL_rgbzLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t r2,fix32_t g2,fix32_t b2); - -void ASMAPI MGL_triFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_cTriFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_rgbTriFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_zTriFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); -void ASMAPI MGL_czTriFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); -void ASMAPI MGL_rgbzTriFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); - -void ASMAPI MGL_quadFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fxpoint_t *v4,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_cQuadFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fxpointc_t *v4,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_rgbQuadFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fxpointrgb_t *v4,fix32_t xOffset,fix32_t yOffset); -void ASMAPI MGL_zQuadFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fxpointz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); -void ASMAPI MGL_czQuadFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fxpointcz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); -void ASMAPI MGL_rgbzQuadFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fxpointrgbz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); -#endif - -/* Routine to set the currently active shade table. In HiColor and TrueColor - * video modes, you must set a valid shadeTable before you call any of the - * color index shaded rendering routines (MGL_cTri() etc). These routines - * will interpolate an index into the current shade table rather than - * each of the RGB color channels, and the appropriate full RGB color is - * extracted directly from the shade table. The shade table can be any size, - * but the application must ensure that the indices passed in are within - * the range of the current shade table. - */ - -#ifdef MGL_3D -void MGLAPI MGL_setShadeTable(color_t *shadeTab); -#endif - -/* Polyline drawing */ - -#ifndef MGL_LITE -void MGLAPI MGL_marker(point_t p); -void MGLAPI MGL_polyPoint(m_int count,point_t *vArray); -void MGLAPI MGL_polyMarker(m_int count,point_t *vArray); -void MGLAPI MGL_polyLine(m_int count,point_t *vArray); -#endif - -/* Rectangle drawing */ - -#ifndef MGL_LITE -void MGLAPI MGL_rectCoord(m_int left,m_int top,m_int right,m_int bottom); -void MGLAPI MGL_fillRectCoord(m_int left,m_int top,m_int right,m_int bottom); -#endif - -/* Scanline color scanning. Thee routines are primitive, and do not perform - * any clipping or viewport mapping, so can be used to build you own - * high performance floodfilling routines (see the example file ffill.c - * for pre-built high speed floodfill routines). - */ - -#ifndef MGL_LITE -m_int ASMAPI MGL_scanRightForColor(m_int x,m_int y,color_t color); -m_int ASMAPI MGL_scanLeftForColor(m_int x,m_int y,color_t color); -m_int ASMAPI MGL_scanRightWhileColor(m_int x,m_int y,color_t color); -m_int ASMAPI MGL_scanLeftWhileColor(m_int x,m_int y,color_t color); -#endif - -/* Psuedo 3D border drawing */ - -#ifndef MGL_LITE -void MGLAPI MGL_drawBorderCoord(m_int left,m_int top,m_int right,m_int bottom,m_int style,m_int thickness); -void MGLAPI MGL_drawHDivider(m_int y,m_int x1,m_int x2); -void MGLAPI MGL_drawVDivider(m_int x,m_int y1,m_int y2); -#endif - -/* Ellipse drawing */ - -#ifndef MGL_LITE -void MGLAPI MGL_ellipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); -void MGLAPI MGL_ellipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle); -void ASMAPI MGL_getArcCoords(arc_coords_t *coords); -void MGLAPI MGL_ellipse(rect_t extentRect); -void MGLAPI MGL_ellipseCoord(m_int x,m_int y,m_int xradius,m_int yradius); -void MGLAPI MGL_fillEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); -void MGLAPI MGL_fillEllipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle); -void MGLAPI MGL_fillEllipse(rect_t extentRect); -void MGLAPI MGL_fillEllipseCoord(m_int x,m_int y,m_int xradius,m_int yradius); -void MGLAPI MGL_ellipseEngine(rect_t extentRect,void (ASMAPI *setup)(m_int topY,m_int botY,m_int left,m_int right),void (ASMAPI *set4pixels)(bool inc_x,bool inc_y,bool region1),void (ASMAPI *finished)(void)); -void MGLAPI MGL_ellipseArcEngine(rect_t extentRect,m_int startAngle,m_int endAngle,arc_coords_t *ac,void (ASMAPI *plotPoint)(m_int x,m_int y)); -#endif - -/* Text attribute manipulation */ - -#ifndef MGL_LITE -void MGLAPI MGL_setTextJustify(m_int horiz,m_int vert); -void MGLAPI MGL_getTextJustify(m_int *horiz,m_int *vert); -void MGLAPI MGL_setTextDirection(m_int direction); -m_int MGLAPI MGL_getTextDirection(void); -void MGLAPI MGL_setTextSize(m_int numerx,m_int denomx,m_int numery,m_int denomy); -void MGLAPI MGL_getTextSize(m_int *numerx,m_int *denomx,m_int *numery,m_int *denomy); -void MGLAPI MGL_setSpaceExtra(m_int extra); -m_int MGLAPI MGL_getSpaceExtra(void); -void MGLAPI MGL_setTextSettings(text_settings_t *settings); -void MGLAPI MGL_getTextSettings(text_settings_t *settings); -m_int MGLAPI MGL_textHeight(void); -m_int MGLAPI MGL_textWidth(const char *str); -void MGLAPI MGL_textBounds(m_int x,m_int y,const char *str,rect_t *bounds); -m_int MGLAPI MGL_charWidth(char ch); -void MGLAPI MGL_getFontMetrics(metrics_t *metrics); -void MGLAPI MGL_getCharMetrics(char ch,metrics_t *metrics); -m_int MGLAPI MGL_maxCharWidth(void); -void MGLAPI MGL_underScoreLocation(m_int *x,m_int *y,const char *str); -#endif - -/* Text drawing */ - -#ifndef MGL_LITE -void MGLAPI MGL_drawStr(const char *str); -void MGLAPI MGL_drawStrXY(m_int x,m_int y,const char *str); -bool MGLAPI MGL_useFont(font_t *font); -font_t * MGLAPI MGL_getFont(void); -bool MGLAPI MGL_vecFontEngine(m_int x,m_int y,const char *str,void (ASMAPI *move)(m_int x,m_int y),void (ASMAPI *draw)(m_int x,m_int y)); -#endif - -/* BitBlt support */ - -void MGLAPI MGL_bitBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int op); -void MGLAPI MGL_stretchBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom); -#ifndef MGL_LITE -void MGLAPI MGL_getDivotCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,void *divot); -void MGLAPI MGL_putDivot(MGLDC *dc,void *divot); -long MGLAPI MGL_divotSizeCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom); -void MGLAPI MGL_putMonoImage(MGLDC *dc,m_int x,m_int y,m_int byteWidth,m_int height,void *image); -void MGLAPI MGL_putBitmap(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,m_int op); -void MGLAPI MGL_putBitmapSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,m_int op); -void MGLAPI MGL_putBitmapTransparent(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,color_t transparent,bool sourceTrans); -void MGLAPI MGL_putBitmapTransparentSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,color_t transparent,bool sourceTrans); -void MGLAPI MGL_putBitmapMask(MGLDC *dc,m_int x,m_int y,const bitmap_t *mask,color_t color); -void MGLAPI MGL_stretchBitmap(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,const bitmap_t *bitmap); -void MGLAPI MGL_putIcon(MGLDC *dc,m_int x,m_int y,const icon_t *icon); -void MGLAPI MGL_transBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,color_t transparent,bool sourceTrans); -#endif - -/* Linear offscreen DC BitBlt support */ - -#ifndef MGL_LITE -void MGLAPI MGL_bitBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,m_int op); -void MGLAPI MGL_transBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,color_t transparent,bool sourceTrans); -#endif - -/* Monochrome bitmap manipulation */ - -#ifndef MGL_LITE -void MGLAPI MGL_drawGlyph(font_t *g,m_int x,m_int y,uchar glyph); -m_int MGLAPI MGL_getGlyphWidth(font_t *font,uchar glyph); -m_int MGLAPI MGL_getGlyphHeight(font_t *font); -void MGLAPI MGL_rotateGlyph(uchar *dst,uchar *src,m_int *byteWidth,m_int *height,m_int rotation); -void MGLAPI MGL_mirrorGlyph(uchar *dst,uchar *src,m_int byteWidth,m_int height); -#endif - -/* Region management */ - -#ifndef MGL_LITE -region_t * MGLAPI MGL_newRegion(void); -region_t * MGLAPI MGL_copyRegion(const region_t *s); -void MGLAPI MGL_clearRegion(region_t *r); -void MGLAPI MGL_freeRegion(region_t *r); -void MGLAPI MGL_drawRegion(m_int x,m_int y,const region_t *r); -#endif - -/* Region generation primitives */ - -#ifndef MGL_LITE -region_t * MGLAPI MGL_rgnLineCoord(m_int x1,m_int y1,m_int x2,m_int y2,const region_t *pen); -region_t * MGLAPI MGL_rgnLineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,const region_t *pen); -/*region_t * MGLAPI MGL_rgnPolygon(m_int count,point_t *vArray);*/ -/*region_t * MGLAPI MGL_rgnPolygonFast(m_int count,point_t *vArray);*/ -region_t * MGLAPI MGL_rgnSolidRectCoord(m_int left,m_int top,m_int right,m_int bottom); -region_t * MGLAPI MGL_rgnEllipse(rect_t extentRect,const region_t *pen); -region_t * MGLAPI MGL_rgnEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle,const region_t *pen); -void MGLAPI MGL_rgnGetArcCoords(arc_coords_t *coords); -region_t * MGLAPI MGL_rgnSolidEllipse(rect_t extentRect); -region_t * MGLAPI MGL_rgnSolidEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); -#endif - -/* Region alegbra */ - -#ifndef MGL_LITE -region_t * MGLAPI MGL_sectRegion(const region_t *r1,const region_t *r2); -region_t * MGLAPI MGL_sectRegionRect(const region_t *r1,const rect_t *r2); -bool MGLAPI MGL_unionRegion(region_t *r1,const region_t *r2); -bool MGLAPI MGL_unionRegionRect(region_t *r1,const rect_t *r2); -bool MGLAPI MGL_unionRegionOfs(region_t *r1,const region_t *r2,m_int xOffset,m_int yOffset); -bool MGLAPI MGL_diffRegion(region_t *r1,const region_t *r2); -bool MGLAPI MGL_diffRegionRect(region_t *r1,const rect_t *r2); -void MGLAPI MGL_optimizeRegion(region_t *r); -void MGLAPI MGL_offsetRegion(region_t *r,m_int dx,m_int dy); -bool MGLAPI MGL_emptyRegion(const region_t *r); -bool MGLAPI MGL_equalRegion(const region_t *r1,const region_t *r2); -bool MGLAPI MGL_ptInRegionCoord(m_int x,m_int y,const region_t *r); -#endif - -/* Region traversal */ - -#ifndef MGL_LITE -typedef void (ASMAPI *rgncallback_t)(const rect_t *r); - -void MGLAPI MGL_traverseRegion(region_t *rgn,rgncallback_t doRect); -#endif - -/* RGB to 8 bit halftone dithering routines */ - -#ifndef MGL_LITE -void MGLAPI MGL_getHalfTonePalette(palette_t *pal); -uchar MGLAPI MGL_halfTonePixel(m_int x,m_int y,uchar R,uchar G,uchar B); -#endif - -/* Resource loading/unloading */ - -font_t * MGLAPI MGL_loadFont(const char *fontname); -bool MGLAPI MGL_availableFont(const char *fontname); -void MGLAPI MGL_unloadFont(font_t *font); -cursor_t * MGLAPI MGL_loadCursor(const char *cursorName); -bool MGLAPI MGL_availableCursor(const char *cursorName); -void MGLAPI MGL_unloadCursor(cursor_t *cursor); -#ifndef MGL_LITE -icon_t * MGLAPI MGL_loadIcon(const char *iconName,bool loadPalette); -bool MGLAPI MGL_availableIcon(const char *iconName); -void MGLAPI MGL_unloadIcon(icon_t *icon); -#endif - -/* Windows BMP bitmap loading/unloading/saving */ - -#ifndef MGL_LITE -bitmap_t * MGLAPI MGL_loadBitmap(const char *bitmapName,bool loadPalette); -bool MGLAPI MGL_availableBitmap(const char *bitmapName); -void MGLAPI MGL_unloadBitmap(bitmap_t *bitmap); -bool MGLAPI MGL_getBitmapSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel,pixel_format_t *pf); -bool MGLAPI MGL_loadBitmapIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette); -bool MGLAPI MGL_saveBitmapFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom); -bitmap_t * MGLAPI MGL_getBitmapFromDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,bool savePalette); -bitmap_t * MGLAPI MGL_buildMonoMask(bitmap_t *bitmap,color_t transparent); -#endif - -/* PCX bitmap loading/unloading/saving (1/4/8 bpp only) */ - -#ifndef MGL_LITE -bitmap_t * MGLAPI MGL_loadPCX(const char *bitmapName,bool loadPalette); -bool MGLAPI MGL_availablePCX(const char *bitmapName); -bool MGLAPI MGL_getPCXSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel); -bool MGLAPI MGL_loadPCXIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette); -bool MGLAPI MGL_savePCXFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom); -#endif - -/* Random number generation routines for shorts and longs with full range */ - -void ASMAPI MGL_srand(m_uint seed); -ushort ASMAPI MGL_random(ushort max); -ulong ASMAPI MGL_randoml(ulong max); - -/* Mouse support */ - -bool MGLAPI MS_available(void); -void MGLAPI MS_show(void); -void MGLAPI MS_hide(void); -void MGLAPI MS_obscure(void); -void MGLAPI MS_setCursor(cursor_t *curs); -void MGLAPI MS_setCursorColor(color_t color); -void MGLAPI MS_moveTo(m_int x,m_int y); -void MGLAPI MS_getPos(m_int *x,m_int *y); -void MGLAPI MS_drawCursor(void); - -/* Rectangle and Point manipulation */ - -rect_t MGLAPI MGL_defRect(m_int left,m_int top,m_int right,m_int bottom); -rect_t MGLAPI MGL_defRectPt(point_t leftTop,point_t rightBottom); -bool MGLAPI MGL_sectRect(rect_t s1,rect_t s2,rect_t *d); -bool MGLAPI MGL_sectRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d); -void MGLAPI MGL_unionRect(rect_t s1,rect_t s2,rect_t *d); -void MGLAPI MGL_unionRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d); - -/* Built-in patterns and mouse cursor */ - -#ifndef MGL_LITE -pattern_t * MGLAPI _MGL_getEmptyPat(void); -pattern_t * MGLAPI _MGL_getGrayPat(void); -pattern_t * MGLAPI _MGL_getSolidPat(void); -#endif -cursor_t * MGLAPI _MGL_getDefCursor(void); - -/* Fixed point multiplication/divide routines */ - -#if defined(__WATCOMC__) && defined(__386__) - -/* For Watcom C++ we can use special inline assembler code that is much - * faster than calling the 386 assembler functions. Currently this is the - * the only compiler that will allow inline assembler to be expanded - * directly as inline functions. - */ - -fix32_t MGL_FixMul(fix32_t a,fix32_t b); -#pragma aux MGL_FixMul = \ - "imul edx" \ - "add eax,8000h" \ - "adc edx,0" \ - "shrd eax,edx,16" \ - parm [eax] [edx] \ - value [eax] \ - modify exact [eax edx]; - -fix32_t MGL_FixDiv(fix32_t a,fix32_t b); -#pragma aux MGL_FixDiv = \ - "xor eax,eax" \ - "shrd eax,edx,16" \ - "sar edx,16" \ - "idiv ebx" \ - parm [edx] [ebx] \ - value [eax] \ - modify exact [eax edx]; - -fix32_t MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c); -#pragma aux MGL_FixMulDiv = \ - "imul ebx" \ - "idiv ecx" \ - parm [eax] [ebx] [ecx] \ - value [eax] \ - modify exact [eax edx]; - -m_int MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2); -#pragma aux MGL_backfacing = \ - "imul ebx" \ - "mov ebx,eax" \ - "mov ecx,edx" \ - "mov eax,esi" \ - "imul edi" \ - "sub eax,ebx" \ - "mov eax,1" \ - "sbb edx,ecx" \ - "jns @@Backfacing" \ - "xor eax,eax" \ - "@@Backfacing:" \ - parm [eax] [esi] [edi] [ebx] \ - value [eax] \ - modify exact [eax ecx edx]; - -void MGL_memcpy(void *dst,void *src,m_int n); -#pragma aux MGL_memcpy = \ - "mov eax,ecx" \ - "shr ecx,2" \ - "rep movsd" \ - "mov cl,al" \ - "and cl,3" \ - "rep movsb" \ - parm [edi] [esi] [ecx] \ - modify exact [eax ecx esi edi]; - -#else - -fix32_t ASMAPI MGL_FixMul(fix32_t a,fix32_t b); -fix32_t ASMAPI MGL_FixDiv(fix32_t a,fix32_t b); -fix32_t ASMAPI MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c); -m_int ASMAPI MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2); -void ASMAPI MGL_memcpy(void *dst,void *src,m_int n); - -#endif - -/* The following are special memcpy routines that properly handler reading - * and writing to virtual linear buffer memory by forcing the proper - * alignment. Note that the copy is extended to use a DWORD copy of speed. - */ - -void ASMAPI MGL_memcpyVIRTSRC(void *dst,void *src,m_int n); -void ASMAPI MGL_memcpyVIRTDST(void *dst,void *src,m_int n); - -/* Function to find an MGL system file's full pathname */ - -bool MGLAPI _MGL_findFile(char *validpath,const char *dir, const char *filename, const char *mode); - -/* Override the internal MGL file I/O functions */ - -void MGLAPI MGL_setFileIO(fileio_t *fio); - -/* The following dummy symbols are used to link in driver files to be used. A - * driver is not active until it is linked in with the MGL_registerDriver - * call. Because we dont export globals in DLLs, we provide functions to - * get the address of the drivers. However for a static link library we - * need to use globals so that if the driver data is unreferenced, it will - * not be linked in with the code. - */ - -#ifndef BUILD_MGL -#if defined(MGL_DLL) && !defined(BUILD_MGLDLL) -void * MGLAPI VGA4_getDriverAddr(void); -void * MGLAPI VGAX_getDriverAddr(void); -void * MGLAPI SVGA4_getDriverAddr(void); -void * MGLAPI SVGA8_getDriverAddr(void); -void * MGLAPI SVGA16_getDriverAddr(void); -void * MGLAPI SVGA24_getDriverAddr(void); -void * MGLAPI SVGA32_getDriverAddr(void); -#if !defined(__16BIT__) -void * MGLAPI VGA8_getDriverAddr(void); -void * MGLAPI LINEAR8_getDriverAddr(void); -void * MGLAPI LINEAR16_getDriverAddr(void); -void * MGLAPI LINEAR24_getDriverAddr(void); -void * MGLAPI LINEAR32_getDriverAddr(void); -void * MGLAPI ACCEL8_getDriverAddr(void); -void * MGLAPI ACCEL16_getDriverAddr(void); -void * MGLAPI ACCEL24_getDriverAddr(void); -void * MGLAPI ACCEL32_getDriverAddr(void); -#if defined(MGLWIN) || defined(__WINDOWS__) -void * MGLAPI DDRAW8_getDriverAddr(void); -void * MGLAPI DDRAW16_getDriverAddr(void); -void * MGLAPI DDRAW24_getDriverAddr(void); -void * MGLAPI DDRAW32_getDriverAddr(void); -#endif -#endif -void * MGLAPI PACKED1_getDriverAddr(void); -void * MGLAPI PACKED4_getDriverAddr(void); -void * MGLAPI PACKED8_getDriverAddr(void); -void * MGLAPI PACKED16_getDriverAddr(void); -void * MGLAPI PACKED24_getDriverAddr(void); -void * MGLAPI PACKED32_getDriverAddr(void); -#define VGA4_driver VGA4_getDriverAddr() -#define VGAX_driver VGAX_getDriverAddr() -#define SVGA4_driver SVGA4_getDriverAddr() -#define SVGA8_driver SVGA8_getDriverAddr() -#define SVGA16_driver SVGA16_getDriverAddr() -#define SVGA24_driver SVGA24_getDriverAddr() -#define SVGA32_driver SVGA32_getDriverAddr() -#if !defined(__16BIT__) -#define VGA8_driver VGA8_getDriverAddr() -#define LINEAR8_driver LINEAR8_getDriverAddr() -#define LINEAR16_driver LINEAR16_getDriverAddr() -#define LINEAR24_driver LINEAR24_getDriverAddr() -#define LINEAR32_driver LINEAR32_getDriverAddr() -#define ACCEL8_driver ACCEL8_getDriverAddr() -#define ACCEL16_driver ACCEL16_getDriverAddr() -#define ACCEL24_driver ACCEL24_getDriverAddr() -#define ACCEL32_driver ACCEL32_getDriverAddr() -#if defined(MGLWIN) || defined(__WINDOWS__) -#define DDRAW8_driver DDRAW8_getDriverAddr() -#define DDRAW16_driver DDRAW16_getDriverAddr() -#define DDRAW24_driver DDRAW24_getDriverAddr() -#define DDRAW32_driver DDRAW32_getDriverAddr() -#endif -#endif -#define PACKED1_driver PACKED1_getDriverAddr() -#define PACKED4_driver PACKED4_getDriverAddr() -#define PACKED8_driver PACKED8_getDriverAddr() -#define PACKED16_driver PACKED16_getDriverAddr() -#define PACKED24_driver PACKED24_getDriverAddr() -#define PACKED32_driver PACKED32_getDriverAddr() -#else -extern m_int _VARAPI VGA4_driver[]; -extern m_int _VARAPI VGAX_driver[]; -extern m_int _VARAPI SVGA4_driver[]; -extern m_int _VARAPI SVGA8_driver[]; -extern m_int _VARAPI SVGA16_driver[]; -extern m_int _VARAPI SVGA24_driver[]; -extern m_int _VARAPI SVGA32_driver[]; -#if !defined(__16BIT__) -extern m_int _VARAPI VGA8_driver[]; -extern m_int _VARAPI LINEAR8_driver[]; -extern m_int _VARAPI LINEAR16_driver[]; -extern m_int _VARAPI LINEAR24_driver[]; -extern m_int _VARAPI LINEAR32_driver[]; -extern m_int _VARAPI ACCEL8_driver[]; -extern m_int _VARAPI ACCEL16_driver[]; -extern m_int _VARAPI ACCEL24_driver[]; -extern m_int _VARAPI ACCEL32_driver[]; -#if defined(MGLWIN) || defined(__WINDOWS__) -extern m_int _VARAPI DDRAW8_driver[]; -extern m_int _VARAPI DDRAW16_driver[]; -extern m_int _VARAPI DDRAW24_driver[]; -extern m_int _VARAPI DDRAW32_driver[]; -#endif -#endif -extern m_int _VARAPI PACKED1_driver[]; -extern m_int _VARAPI PACKED4_driver[]; -extern m_int _VARAPI PACKED8_driver[]; -extern m_int _VARAPI PACKED16_driver[]; -extern m_int _VARAPI PACKED24_driver[]; -extern m_int _VARAPI PACKED32_driver[]; -#endif -#endif - -/*--------------------------------------------------------------------------- - * Memory allocation and utility functions. - *-------------------------------------------------------------------------*/ - -#ifndef __16BIT__ -#define _HUGE -#else -#define _HUGE _huge -#endif - -void MGL_availableMemory(ulong *physical,ulong *total); -void MGL_useLocalMalloc(void _HUGE * (*malloc)(long size),void (*free)(void _HUGE *p)); -void * MGLAPI MGL_malloc(long size); -void * MGLAPI MGL_calloc(long size,long n); -void MGLAPI MGL_free(void _HUGE *p); -void MGLAPI MGL_memset(void _HUGE *s,m_int c,long n); -void MGLAPI MGL_memsetw(void _HUGE *s,m_int c,long n); -void MGLAPI MGL_memsetl(void _HUGE *s,long c,long n); - -/*--------------------------------------------------------------------------- - * Set a fullscreen suspend application callback function. This is used in - * fullscreen video modes to allow switching back to the normal operating - * system graphical shell (such as Windows GDI, OS/2 PM etc). - *-------------------------------------------------------------------------*/ - -typedef m_int (ASMAPI *MGL_suspend_cb_t)(MGLDC *dc,m_int flags); -void MGLAPI MGL_setSuspendAppCallback(MGL_suspend_cb_t staveState); - -/*--------------------------------------------------------------------------- - * Tell the MGL to use a pre-loaded ACCEL.DRV driver file. This allows - * you to link with the SciTech WinDirect/Pro and WinDirect/Ultra device - * support libraries and tell the MGL to use the device support drivers. - * If the user has a real ACCEL.DRV driver file in the standard location - * on their machine, this driver file will still be used. - *-------------------------------------------------------------------------*/ - -void MGLAPI MGL_setACCELDriver(void *driver); - -/*---------------------- Inline functions as Macros -----------------------*/ - -#define MGL_equalPoint(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y) - -#define MGL_equalRect(r1,r2) ((r1).left == (r2).left && \ - (r1).top == (r2).top && \ - (r1).right == (r2).right && \ - (r1).bottom == (r2).bottom) - -#define MGL_emptyRect(r) ((r).bottom <= (r).top || \ - (r).right <= (r).left) - -#define MGL_disjointRect(r1,r2) ((r1).right <= (r2).left || \ - (r1).left >= (r2).right || \ - (r1).bottom <= (r2).top || \ - (r1).top >= (r2).bottom) - -#define MGL_sectRect(s1,s2,d) \ - ((d)->left = MAX((s1).left,(s2).left), \ - (d)->right = MIN((s1).right,(s2).right), \ - (d)->top = MAX((s1).top,(s2).top), \ - (d)->bottom = MIN((s1).bottom,(s2).bottom), \ - !MGL_emptyRect(*d)) - -#define MGL_sectRectFast(s1,s2,d) \ - (d)->left = MAX((s1).left,(s2).left); \ - (d)->right = MIN((s1).right,(s2).right); \ - (d)->top = MAX((s1).top,(s2).top); \ - (d)->bottom = MIN((s1).bottom,(s2).bottom) - -#define MGL_sectRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ - ((d)->left = MAX(l1,l2), \ - (d)->right = MIN(r1,r2), \ - (d)->top = MAX(t1,t2), \ - (d)->bottom = MIN(b1,b2), \ - !MGL_emptyRect(*d)) - -#define MGL_sectRectFastCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ - (d)->left = MAX(l1,l2); \ - (d)->right = MIN(r1,r2); \ - (d)->top = MAX(t1,t2); \ - (d)->bottom = MIN(b1,b2) - -#define MGL_unionRect(s1,s2,d) \ - (d)->left = MIN((s1).left,(s2).left); \ - (d)->right = MAX((s1).right,(s2).right); \ - (d)->top = MIN((s1).top,(s2).top); \ - (d)->bottom = MAX((s1).bottom,(s2).bottom) - -#define MGL_unionRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ - (d)->left = MIN(l1,l2); \ - (d)->right = MAX(r1,r2); \ - (d)->top = MIN(t1,t2); \ - (d)->bottom = MAX(b1,b2) - -#define MGL_offsetRect(r,dx,dy) \ - { (r).left += dx; (r).right += dx; \ - (r).top += dy; (r).bottom += dy; } - -#define MGL_insetRect(r,dx,dy) \ - { (r).left += dx; (r).right -= dx; \ - (r).top += dy; (r).bottom -= dy; \ - if (MGL_emptyRect(r)) \ - (r).left = (r).right = (r).top = (r).bottom = 0; } - -#define MGL_ptInRect(p,r) ((p).x >= (r).left && \ - (p).x < (r).right && \ - (p).y >= (r).top && \ - (p).y < (r).bottom) - -#define MGL_ptInRectCoord(x,y,r) ((x) >= (r).left && \ - (x) < (r).right && \ - (y) >= (r).top && \ - (y) < (r).bottom) - -#define MGL_ptInRegion(p,r) MGL_ptInRegionCoord((p).x,(p).y,r) - -#define MGL_pixel(p) MGL_pixelCoord((p).x,(p).y) -#define MGL_getPixel(p) MGL_getPixelCoord((p).x,(p).y) -#define MGL_pixelFast(p) MGL_pixelCoordFast((p).x,(p).y) -#define MGL_getPixelFast(p) MGL_getPixelCoordFast((p).x,(p).y) -#define MGL_moveTo(p) MGL_moveToCoord((p).x,(p).y) -#define MGL_moveRel(p) MGL_moveRelCoord((p).x,(p).y) -#define MGL_line(p1,p2) MGL_lineCoord((p1).x,(p1).y,(p2).x,(p2).y) -#define MGL_lineFast(p1,p2) MGL_lineCoordFast((p1).x,(p1).y,(p2).x,(p2).y) -#define MGL_lineFX(p1,p2) MGL_lineCoordFX((p1).x,(p1).y,(p2).x,(p2).y) -#define MGL_lineFastFX(p1,p2) MGL_lineCoordFastFX((p1).x,(p1).y,(p2).x,(p2).y) -#define MGL_cLineFast(p1,p2) MGL_cLineCoordFast((p1).p.x,(p1).p.y,(p1).c,(p2).p.x,(p2).p.y,(p2).c) -#define MGL_rgbLineFast(p1,p2) MGL_rgbLineCoordFast((p1).p.x,(p1).p.y,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).c.r,(p2).c.g,(p2).c.b) -#define MGL_zLineFast(p1,p2) MGL_zLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p2).p.x,(p2).p.y,(p2).z) -#define MGL_czLineFast(p1,p2) MGL_czLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c,(p2).p.x,(p2).p.y,(p2).z,(p2).c) -#define MGL_rgbzLineFast(p1,p2) MGL_rgbzLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).z,(p2).c.r,(p2).c.g,(p2).c.b) - -#define MGL_zClearPt(lt,rb,z) MGL_zClearCoord((lt).x,(lt).y, \ - (rb).x,(rb).y,z) -#define MGL_zClear(r,z) MGL_zClearCoord((r).left,(r).top, \ - (r).right,(r).bottom,z) -#define MGL_lineTo(p) MGL_lineToCoord((p).x,(p).y) -#define MGL_lineRel(p) MGL_lineRelCoord((p).x,(p).y); -#define MGL_rectPt(lt,rb) MGL_rectCoord((lt).x,(lt).y,(rb).x,(rb).y) -#define MGL_rect(r) MGL_rectCoord((r).left,(r).top, \ - (r).right,(r).bottom) -#define MGL_drawBorder(r,s,t) MGL_drawBorderCoord((r).left,(r).top, \ - (r).right,(r).bottom,(s),(t)) -#define MGL_fillRectPt(lt,rb) MGL_fillRectCoord((lt).x,(lt).y, \ - (rb).x,(rb).y) -#define MGL_fillRect(r) MGL_fillRectCoord((r).left,(r).top, \ - (r).right,(r).bottom) -#define MGL_bitBlt(d,s,r,dl,dt,op) MGL_bitBltCoord((d),(s),(r).left, \ - (r).top,(r).right,(r).bottom,dl,dt,op) -#define MGL_bitBltLin(d,s,so,r,op) MGL_bitBltLinCoord((d),(s),so, \ - (r).left,(r).top,(r).right,(r).bottom,op) -#define MGL_stretchBlt(d,s,sr,dr) MGL_stretchBltCoord((d),(s),(sr).left, \ - (sr).top,(sr).right,(sr).bottom, \ - (dr).left,(dr).top,(dr).right,(dr).bottom) -#define MGL_transBlt(d,s,r,dl,dt,c,st) MGL_transBltCoord((d),(s),(r).left, \ - (r).top,(r).right,(r).bottom,dl,dt,c,st) -#define MGL_transBltLin(d,s,so,r,c,st) MGL_transBltLinCoord((d),(s),so, \ - (r).left,(r).top,(r).right,(r).bottom,c,st) -#define MGL_getDivot(dc,r,divot) MGL_getDivotCoord(dc,(r).left,(r).top, \ - (r).right,(r).bottom,divot) -#define MGL_divotSize(dc,r) MGL_divotSizeCoord(dc,(r).left,(r).top,\ - (r).right,(r).bottom) -#define MGL_isSimpleRegion(r) (((region_t*)(r))->spans == NULL) -#define MGL_rgnLine(p1,p2,p) MGL_rgnLineCoord((p1).x,(p1).y,(p2).x,(p2).y,p) -#define MGL_rgnLineFX(p1,p2,p) MGL_rgnLineCoordFX((p1).x,(p1).y,(p2).x,(p2).y,p) -#define MGL_rgnSolidRectPt(lt,rb) MGL_rgnSolidRectCoord((lt).x,(lt).y, \ - (rb).x,(rb).y) -#define MGL_rgnSolidRect(r) MGL_rgnSolidRectCoord((r).left,(r).top, \ - (r).right,(r).bottom) - -/* Fast color packing/unpacking routines implemented as macros */ - -#define MGL_packColorFast(pf,R,G,B) \ - ((ulong)(((uchar)(R) >> (pf)->redAdjust) & (pf)->redMask) << (pf)->redPos) \ - | ((ulong)(((uchar)(G) >> (pf)->greenAdjust) & (pf)->greenMask) << (pf)->greenPos) \ - | ((ulong)(((uchar)(B) >> (pf)->blueAdjust) & (pf)->blueMask) << (pf)->bluePos) - -#define MGL_unpackColorFast(pf,c,R,G,B) \ -{ \ - (R) = (uchar)((((ulong)(c) >> (pf)->redPos) & (pf)->redMask) << (pf)->redAdjust); \ - (G) = (uchar)((((ulong)(c) >> (pf)->greenPos) & (pf)->greenMask) << (pf)->greenAdjust);\ - (B) = (uchar)((((ulong)(c) >> (pf)->bluePos) & (pf)->blueMask) << (pf)->blueAdjust); \ -} - -/* Macros to access the RGB components in a packed 24 bit RGB tuple */ - -#define MGL_rgbRed(c) (((uchar*)&(c))[2]) -#define MGL_rgbGreen(c) (((uchar*)&(c))[1]) -#define MGL_rgbBlue(c) (((uchar*)&(c))[0]) - -/* Fast 24 bit color packing/unpacking routines implemented as macros */ - -#define MGL_packColorRGBFast(R,G,B) \ - (((ulong)((uchar)(R)) << 16) | ((ulong)((uchar)(G)) << 8) | (uchar)(B)) - -#define MGL_packColorRGBFast2(c,R,G,B) \ -{ \ - MGL_rgbRed(c) = (uchar)(R); \ - MGL_rgbGreen(c) = (uchar)(G); \ - MGL_rgbBlue(c) = (uchar)(B); \ -} - -#define MGL_unpackColorRGBFast(c,R,G,B) \ -{ \ - (R) = MGL_rgbRed(c); \ - (G) = MGL_rgbGreen(c); \ - (B) = MGL_rgbBlue(c); \ -} - -#ifdef __cplusplus -} /* End of "C" linkage for C++ */ - -#include "mglrect.hpp" /* Include C++ point/rectangle classes */ - -#endif /* __cplusplus */ - -/* Include appropriate platform specific bindings */ - -#if defined(MGLWIN) || defined(__WINDOWS__) -#include "mglwin.h" -#elif defined(MGLPM) || defined(__OS2__) -/*#include "mglpm.h"*/ -#elif defined(MGLX) || defined(__UNIX__) -/*#include "mglx.h"*/ -#else -#include "mgldos.h" -#endif - -#pragma pack() /* Return to default packing */ - -#endif /* __MGRAPH_H */ +/**************************************************************************** +* +* MegaGraph Graphics Library +* +* Copyright (C) 1996 SciTech Software. +* All rights reserved. +* +* Filename: $Workfile: mgraph.h $ +* Version: $Revision: 1.29 $ +* +* Language: ANSI C +* Environment: IBM PC (MS DOS) +* +* Description: Header file for the MegaGraph Graphics Library. You can +* defined one of the following to specify which MGL API you +* wish to use. +* +* MGL_LITE - Compile for the MGL/Lite API +* MGL_PRO - Compile for the MGL/Pro API +* MGL_FIX3D - Compile for the MGL/3D API (fixed point) +* MGL_FLT3D - Compile for the MGL/3D API (floating point) +* +* If you do not define any of these, MGL_FIX3D will be defined +* automatically for compatibility with older versions of the +* MGL. +* +* $Date: 11 Mar 1997 16:46:42 $ $Author: KendallB $ +* +****************************************************************************/ + +#ifndef __MGRAPH_H +#define __MGRAPH_H + +#include + +#ifndef __DEBUG_H +#include "debug.h" +#endif + +#if !defined(MGL_LITE) && !defined(MGL_PRO) && !defined(MGL_FIX3D) \ + && !defined(MGL_FLT3D) +#define MGL_FIX3D +#endif + +#if defined(MGL_FIX3D) || defined(MGL_FLT3D) +#define MGL_3D +#endif + +/*---------------------- Macros and type definitions ----------------------*/ + +#pragma pack(1) /* Pack structures to byte granularity */ + +/* Define the version number for the MGL release */ + +#define MGL_VERSION_STR "3.1" + +/* Define the calling conventions for all public MGL functions. If we + * are compiling the MGL as a DLL, then all public functions are compiled + * and exported with standard C calling conventions, otherwise we use + * the default calling conventions provided by the compiler. + * + * Note that because Watcom C++ uses register based parameter passing + * by default we also provide special DLL's for watcom that are compiled + * with register parameter passing. This is necessary to work with all + * the extra libraries provided as they are all compiled to call MGL + * functions with arguments in registers whenever possible. You can still + * use the standard DLL but if you do you will need to re-compile all + * of the extra libraries with the MGL_DLL #define to change the calling + * conventions for the MGL functions. + */ + +#if defined(MGL_DLL) +#define MGLAPI _EXPORT __cdecl +#else +#define MGLAPI _EXPORT _PUBAPI +#endif +#define ASMAPI _EXPORT __cdecl + +/* Define a type for integers used in the library. For most environments + * we simply define it as a normal integer (16 or 32 bits), however for + * 16 bit Windows it is defined as a 32 bit integer as all the real code + * lives in a 32 bit DLL that uses 32 bit integers. + */ + +#ifndef __M_INT_DEFINED +#if defined(__WINDOWS16__) +typedef long m_int; +typedef unsigned long m_uint; +#else +typedef int m_int; +typedef unsigned int m_uint; +#endif +#define __M_INT_DEFINED +#endif + +/* Define the graphics subsystems available */ + +typedef enum { + grDETECT = -1, /* Auto detect the graphics subsystem */ + grNONE = 0, /* No graphics hardware detected */ + grVGA, /* Standard VGA */ + grVESA, /* VESA VBE compliant SuperVGA */ + grSVGA, /* Unaccelerated SuperVGA */ + grACCEL, /* Accelerated SuperVGA */ + grDDRAW, /* Unaccelerated DirectDraw */ + grDDRAWACCEL, /* Accelerated DirectDraw */ + grDDRAW3D, /* 3D Accelerated DirectDraw */ + grMAXDRIVER, /* Maximum driver number */ + } MGL_driverType; + +/* Graphics modes supported - the only video modes supported by this + * graphics library are those that support at least 16 colors per pixel. + */ + +typedef enum { + /* 16 color VGA video modes */ + + grVGA_320x200x16, + grVGA_640x200x16, + grVGA_640x350x16, + grVGA_640x400x16, + grVGA_640x480x16, + grSVGA_800x600x16, + + /* 256 color VGA ModeX video modes */ + + grVGAX_320x200x256, + grVGAX_320x240x256, + grVGAX_320x400x256, + grVGAX_320x480x256, + + /* 256 color VGA video modes */ + + grVGA_320x200x256, + + /* 256 color VGA/SuperVGA video modes */ + + grSVGA_320x200x256, + grSVGA_320x240x256, + grSVGA_320x400x256, + grSVGA_320x480x256, + grSVGA_400x300x256, + grSVGA_512x384x256, + grSVGA_640x350x256, + grSVGA_640x400x256, + grSVGA_640x480x256, + grSVGA_800x600x256, + grSVGA_1024x768x256, + grSVGA_1152x864x256, + grSVGA_1280x960x256, + grSVGA_1280x1024x256, + grSVGA_1600x1200x256, + + /* 32,768 color Super VGA video modes */ + + grSVGA_320x200x32k, + grSVGA_320x240x32k, + grSVGA_320x400x32k, + grSVGA_320x480x32k, + grSVGA_400x300x32k, + grSVGA_512x384x32k, + grSVGA_640x350x32k, + grSVGA_640x400x32k, + grSVGA_640x480x32k, + grSVGA_800x600x32k, + grSVGA_1024x768x32k, + grSVGA_1152x864x32k, + grSVGA_1280x960x32k, + grSVGA_1280x1024x32k, + grSVGA_1600x1200x32k, + + /* 65,536 color Super VGA video modes */ + + grSVGA_320x200x64k, + grSVGA_320x240x64k, + grSVGA_320x400x64k, + grSVGA_320x480x64k, + grSVGA_400x300x64k, + grSVGA_512x384x64k, + grSVGA_640x350x64k, + grSVGA_640x400x64k, + grSVGA_640x480x64k, + grSVGA_800x600x64k, + grSVGA_1024x768x64k, + grSVGA_1152x864x64k, + grSVGA_1280x960x64k, + grSVGA_1280x1024x64k, + grSVGA_1600x1200x64k, + + /* 16 million color, 24 bits per pixel Super VGA video modes */ + + grSVGA_320x200x16m, + grSVGA_320x240x16m, + grSVGA_320x400x16m, + grSVGA_320x480x16m, + grSVGA_400x300x16m, + grSVGA_512x384x16m, + grSVGA_640x350x16m, + grSVGA_640x400x16m, + grSVGA_640x480x16m, + grSVGA_800x600x16m, + grSVGA_1024x768x16m, + grSVGA_1152x864x16m, + grSVGA_1280x960x16m, + grSVGA_1280x1024x16m, + grSVGA_1600x1200x16m, + + /* 16 million color, 32 bits per pixel Super VGA video modes */ + + grSVGA_320x200x4G, + grSVGA_320x240x4G, + grSVGA_320x400x4G, + grSVGA_320x480x4G, + grSVGA_400x300x4G, + grSVGA_512x384x4G, + grSVGA_640x350x4G, + grSVGA_640x400x4G, + grSVGA_640x480x4G, + grSVGA_800x600x4G, + grSVGA_1024x768x4G, + grSVGA_1152x864x4G, + grSVGA_1280x960x4G, + grSVGA_1280x1024x4G, + grSVGA_1600x1200x4G, + + /* Render into Windowing System DC (Windows, OS/2 PM, X11) */ + + grWINDOWED, + + grMAXMODE, /* Maximum mode number */ + } MGL_modeType; + +/* MGL_result() error codes */ + +typedef enum { + grOK = 0, /* No error */ + grNoInit = -1, /* Graphics driver has not been installed */ + grNotDetected = -2, /* Graphics hardware was not detected */ + grDriverNotFound= -3, /* Graphics driver file not found */ + grBadDriver = -4, /* File loaded was not a graphics driver */ + grLoadMem = -5, /* Not enough memory to load graphics driver*/ + grInvalidMode = -6, /* Invalid graphics mode for selected driver*/ + grError = -8, /* General graphics error */ + grInvalidName = -9, /* Invalid driver name */ + grNoMem = -10, /* Not enough memory to perform operation */ + grNoModeSupport = -11, /* Select video mode not supported by hard. */ + grInvalidFont = -12, /* Invalid font data */ + grBadFontFile = -13, /* File loaded was not a font file */ + grFontNotFound = -14, /* Font file was not found */ + grOldDriver = -15, /* Driver file is an old version */ + grInvalidDevice = -16, /* Invalid device for selected operation */ + grInvalidDC = -17, /* Invalid device context */ + grInvalidCursor = -18, /* Invalid cursor file */ + grCursorNotFound= -19, /* Cursor file was not found */ + grInvalidIcon = -20, /* Invalid icon file */ + grIconNotFound = -21, /* Icon file was not found */ + grInvalidBitmap = -22, /* Invalid bitmap file */ + grBitmapNotFound= -23, /* Bitmap file was not found */ + grZbufferTooBig = -24, /* Zbuffer allocation is too large */ + grNewFontFile = -25, /* Only Windows 2.x font files supported */ + grNoDoubleBuff = -26, /* Double buffering is not available */ + grNoHardwareBlt = -28, /* No hardware bitBlt for OffscreenDC */ + grNoOffscreenMem= -29, /* No available offscreen memory */ + grInvalidPF = -30, /* Invalid pixel format for memory DC */ + + grLastError = -31, /* Last error number in list */ + } MGL_errorType; + +#define MGL_CLIPON true +#define MGL_CLIPOFF false + +/* Color mapped modes */ + +typedef enum { + MGL_CMAP_MODE, /* Normal Color mapped mode */ + MGL_DITHER_RGB_MODE, /* 24 bit RGB halftone dithered */ + } MGL_colorModes; + +/* Standard colors - this is the standard set of colors for the IBM PC. The + * default palette will have been programmed to contain these values when a + * graphics modes is started. If the palette has been changed, they will + * not correspond to the actual colors on the screen. Under a Windowing + * manage environment these colors will also not be setup by default. + */ + +enum MGL_COLORS { + MGL_BLACK, /* dark colors */ + MGL_BLUE, + MGL_GREEN, + MGL_CYAN, + MGL_RED, + MGL_MAGENTA, + MGL_BROWN, + MGL_LIGHTGRAY, + MGL_DARKGRAY, /* light colors */ + MGL_LIGHTBLUE, + MGL_LIGHTGREEN, + MGL_LIGHTCYAN, + MGL_LIGHTRED, + MGL_LIGHTMAGENTA, + MGL_YELLOW, + MGL_WHITE, + }; + +/* Windows standard color indices for 256 color bitmaps. 8,9,246,247 are + * reserved and you should not count on these colors always being the + * same. For 16 color bitmaps, colors 248-255 map to colors 8-15. + */ + +enum MGL_WIN_COLORS { + MGL_WIN_BLACK = 0, + MGL_WIN_DARKRED = 1, + MGL_WIN_DARKGREEN = 2, + MGL_WIN_DARKYELLOW = 3, + MGL_WIN_DARKBLUE = 4, + MGL_WIN_DARKMAGENTA = 5, + MGL_WIN_DARKCYAN = 6, + MGL_WIN_LIGHTGRAY = 7, + MGL_WIN_TURQUOISE = 8, /* Reserved; dont count on this */ + MGL_WIN_SKYBLUE = 9, /* Reserved; dont count on this */ + MGL_WIN_CREAM = 246, /* Reserved; dont count on this */ + MGL_WIN_MEDIUMGRAY = 247, /* Reserved; dont count on this */ + MGL_WIN_DARKGRAY = 248, + MGL_WIN_LIGHTRED = 249, + MGL_WIN_LIGHTGREEN = 250, + MGL_WIN_LIGHTYELLOW = 251, + MGL_WIN_LIGHTBLUE = 252, + MGL_WIN_LIGHTMAGENTA = 253, + MGL_WIN_LIGHTCYAN = 254, + MGL_WIN_WHITE = 255, + }; + +typedef enum { + MGL_MARKER_SQUARE, + MGL_MARKER_CIRCLE, + MGL_MARKER_X, + } MGL_markerStyleType; + +typedef enum { /* Write mode operators */ + MGL_REPLACE_MODE, /* Replace mode */ + MGL_AND_MODE, /* AND mode */ + MGL_OR_MODE, /* OR mode */ + MGL_XOR_MODE, /* XOR mode */ + } MGL_writeModeType; + +typedef enum { + MGL_BITMAP_SOLID, + MGL_BITMAP_OPAQUE, + MGL_BITMAP_TRANSPARENT, + MGL_PIXMAP, + } MGL_fillStyleType; + +typedef enum { + MGL_LINE_PENSTYLE, /* Line drawn in current pen style */ + MGL_LINE_STIPPLE, /* Line drawn with current stipple */ + } MGL_lineStyleType; + +typedef enum { + MGL_CONVEX_POLYGON, /* Monotone vertical polygon */ + MGL_COMPLEX_POLYGON, /* Non-Simple polygons */ + MGL_AUTO_POLYGON, /* Auto detect the polygon type */ + } MGL_polygonType; + +/* Text manipulation defines */ + +typedef enum { + MGL_LEFT_TEXT = 0, /* Justify from left */ + MGL_TOP_TEXT = 0, /* Justify from top */ + MGL_CENTER_TEXT = 1, /* Center the text */ + MGL_RIGHT_TEXT = 2, /* Justify from right */ + MGL_BOTTOM_TEXT = 2, /* Justify from bottom */ + MGL_BASELINE_TEXT = 3, /* Justify from the baseline */ + } MGL_textJustType; + +typedef enum { + MGL_LEFT_DIR = 0, /* Text goes to left */ + MGL_UP_DIR = 1, /* Text goes up */ + MGL_RIGHT_DIR = 2, /* Text goes right */ + MGL_DOWN_DIR = 3, /* Text goes down */ + } MGL_textDirType; + +/* Font types */ + +typedef enum { + MGL_VECTORFONT = 1, /* Vector font */ + MGL_FIXEDFONT, /* Fixed width bitmap font */ + MGL_PROPFONT, /* Proportional width bitmap font */ + } MGL_fontType; + +/* Palette rotation directions */ + +typedef enum { + MGL_ROTATE_UP, /* Rotate the palette values up */ + MGL_ROTATE_DOWN, /* Rotate the palette values down */ + } MGL_palRotateType; + +/* Border drawing routine styles */ + +typedef enum { + MGL_BDR_INSET, /* Interior is inset into screen */ + MGL_BDR_OUTSET, /* Interior is outset from screen */ + MGL_BDR_OUTLINE, /* Border is 3d outline */ + } MGL_bdrStyleType; + +/* Standard display driver names */ + +#define MGL_VGA4NAME "VGA4.DRV" /* Standard VGA drivers */ +#define MGL_VGA8NAME "VGA8.DRV" +#define MGL_VGAXNAME "VGAX.DRV" + +#define MGL_SVGA4NAME "SVGA4.DRV" /* Generic SuperVGA drivers */ +#define MGL_SVGA8NAME "SVGA8.DRV" +#define MGL_SVGA16NAME "SVGA16.DRV" +#define MGL_SVGA24NAME "SVGA24.DRV" +#define MGL_SVGA32NAME "SVGA32.DRV" + +#define MGL_LINEAR8NAME "LINEAR8.DRV" /* Linear framebuffer drivers */ +#define MGL_LINEAR16NAME "LINEAR16.DRV" +#define MGL_LINEAR24NAME "LINEAR24.DRV" +#define MGL_LINEAR32NAME "LINEAR32.DRV" + +#define MGL_ACCEL8NAME "ACCEL8.DRV" /* VBE/AF Accelerated drivers */ +#define MGL_ACCEL16NAME "ACCEL16.DRV" +#define MGL_ACCEL24NAME "ACCEL24.DRV" +#define MGL_ACCEL32NAME "ACCEL32.DRV" + +#define MGL_DDRAW8NAME "DDRAW8.DRV" /* DirectDraw drivers */ +#define MGL_DDRAW16NAME "DDRAW16.DRV" +#define MGL_DDRAW24NAME "DDRAW24.DRV" +#define MGL_DDRAW32NAME "DDRAW32.DRV" + +/* Standard memory driver names */ + +#define MGL_PACKED1NAME "PACK1.DRV" +#define MGL_PACKED4NAME "PACK4.DRV" +#define MGL_PACKED8NAME "PACK8.DRV" +#define MGL_PACKED16NAME "PACK16.DRV" +#define MGL_PACKED24NAME "PACK24.DRV" +#define MGL_PACKED32NAME "PACK32.DRV" + +/* Standard bitmap names */ + +#define MGL_EMPTY_FILL _MGL_getEmptyPat() +#define MGL_GRAY_FILL _MGL_getGrayPat() +#define MGL_SOLID_FILL _MGL_getSolidPat() + +/* Event message masks for keyDown events */ + +#define EVT_ASCIIMASK 0x00FF /* Ascii code of key pressed */ +#define EVT_SCANMASK 0xFF00 /* Scan code of key pressed */ +#define EVT_COUNTMASK 0x7FFF0000L /* Count for KEYREPEAT's */ + +#define EVT_asciiCode(m) ( (uchar) (m & EVT_ASCIIMASK) ) +#define EVT_scanCode(m) ( (uchar) ( (m & EVT_SCANMASK) >> 8 ) ) +#define EVT_repeatCount(m) ( (short) ( (m & EVT_COUNTMASK) >> 16 ) ) + +/* Event message masks for mouse events */ + +#define EVT_LEFTBMASK 0x0001 /* Left button is bit 0 */ +#define EVT_RIGHTBMASK 0x0004 /* Right button is bit 1 */ +#define EVT_BOTHBMASK 0x0005 /* Both left and right together */ +#define EVT_ALLBMASK 0x0005 /* All buttons pressed */ + +/* Modifier masks */ + +#define EVT_LEFTBUT 0x0001 /* Set if left button was down */ +#define EVT_RIGHTBUT 0x0002 /* Set if right button was down */ +#define EVT_RIGHTSHIFT 0x0008 /* Set if right shift down */ +#define EVT_LEFTSHIFT 0x0010 /* Set if left shift down */ +#define EVT_CTRLSTATE 0x0020 /* Set if ctrl key down */ +#define EVT_ALTSTATE 0x0040 /* Set if alt key down */ +#define EVT_LEFTCTRL 0x0080 /* Set if left ctrl key down */ +#define EVT_LEFTALT 0x0100 /* Set if left alt key down */ +#define EVT_SHIFTKEY 0x0018 /* Any shift key */ + +/* Event codes */ + +#define EVT_NULLEVT 0x0000 /* A null event */ +#define EVT_KEYDOWN 0x0001 /* Key down event */ +#define EVT_KEYREPEAT 0x0002 /* Key repeat event */ +#define EVT_KEYUP 0x0004 /* Key up event */ +#define EVT_MOUSEDOWN 0x0008 /* Mouse down event */ +#define EVT_MOUSEUP 0x0010 /* Mouse up event */ +#define EVT_MOUSEMOVE 0x0020 /* Mouse movement event */ +#define EVT_TIMERTICK 0x0040 /* Timer tick event */ +#define EVT_USEREVT 0x0080 /* First user event */ + +/* Event code masks */ + +#define EVT_KEYEVT (EVT_KEYDOWN | EVT_KEYREPEAT | EVT_KEYUP) +#define EVT_MOUSEEVT (EVT_MOUSEDOWN | EVT_MOUSEUP | EVT_MOUSEMOVE) +#define EVT_MOUSECLICK (EVT_MOUSEDOWN | EVT_MOUSEUP) +#define EVT_EVERYEVT 0xFFFF + +/* Suspend Application callback type codes. This callback is called + * when the user presses one of the corresponding keys indicating that + * they wish to change the active application. The MGL will catch these + * events and if you have registered a callback, will call the callback to + * save the state of the application so that it can be properly restored + * when the user switches back to your application. The MGL takes care of + * all the details about saving and restoring the state of the hardware, + * and all your application needs to do is save its own state so that you can + * re-draw the application screen upon re-activation. + * + * NOTE: Your application suspend callback may get called twice with the + * MGL_DEACTIVATE flag in order to test whether the switch should + * occur (under both DirectDraw and WinDirect fullscreen modes). + * + * NOTE: When your callback is called with the MGL_DEACTIVATE flag, you + * cannot assume that you have access to the display memory surfaces + * as they may have been lost by the time your callback has been called. + */ + +#define MGL_DEACTIVATE 0x0001 /* Application losing active focus */ +#define MGL_REACTIVATE 0x0002 /* Application regaining active focus */ + +/* Return codes from the suspend application callback. The normal value + * to be returned is MGL_SUSPEND_APP and this will cause the app to be + * suspended while back in GDI mode until the app is re-activated again + * by the user. + * + * MGL_NO_DEACTIVATE signals to WinDirect that the application does not want + * to allow switching to occur, and the switch request will be ignored and + * the app will remain in fullscreen mode. + * + * MGL_NO_SUSPEND_APP can be used to tell WinDirect to switch back to the + * desktop, but not to suspend the application. This must be used with + * care as the suspend application callback is then responsible for setting + * a flag in the application that will stop the application from doing any + * rendering to the framebuffer while the application is in GDI mode. This + * return value is useful for games that need to maintain network + * connectivity while the user has temporarily switched back to GDI mode. + */ + +#define MGL_NO_DEACTIVATE 0 /* Dont allow app to be deactivated */ +#define MGL_SUSPEND_APP 1 /* Suspend application until restored */ +#define MGL_NO_SUSPEND_APP 2 /* Dont suspend, but allow switch */ + +/* Here we define the structures used to represent points and rectangles */ + +typedef struct { + m_int x,y; + } point_t; + +typedef struct { + m_int left; + m_int top; + m_int right; + m_int bottom; + } rect_t; + +/* All colors are represented as longs by the library. This allows + * code to work correctly with up to 24 bit color device drivers. The + * device drivers themselves expect the color to be a color index if in + * a color mapped mode, or a 15/16/24 bit RGB tuple in a hicolor or truecolor + * mode. You can use the appropriate routines to pack and unpack + * colors into the color_t format. + */ + +typedef ulong color_t; + +/* Define the value used to clear the software ZBuffer. The MGL always uses + * a > operator for the z compare, and the smallest value is 0. + */ + +#define MGL_ZCLEARVAL 0 + +/* Structures for passing vertex information to polygon rendering routines. + * All fixed point coordinates are passed in 16.16 signed fixed point + * format, while zbuffer coordinates are passed in 4.28 signed fixed point + * format. The sign bit is used purely for overflow and arithmetic + * internally, and all user passed zbuffer values should be greater than + * 0. All shaded rendering routines either take a color index in 8.16 fixed + * point format (range 0-255.9) or separate RGB components in 8.16 fixed + * point format (range 0-255.9). + */ + +#ifdef __FX_FIXED_H +#define fix32_t FXFixed +#else +typedef long fix32_t; +#endif +typedef fix32_t fxcolor_t; +typedef long zfix32_t; + +typedef struct { + fix32_t x,y; + } fxpoint_t; + +typedef struct { + fxcolor_t r,g,b; + } fxrgb_t; + +typedef struct { + fix32_t w,s,t; + } fxtex_t; + +typedef struct { + fxcolor_t c; + fxpoint_t p; + } fxpointc_t; + +typedef struct { + fxrgb_t c; + fxpoint_t p; + } fxpointrgb_t; + +typedef struct { + fxpoint_t p; + zfix32_t z; + } fxpointz_t; + +typedef struct { + fxcolor_t c; + fxpoint_t p; + zfix32_t z; + } fxpointcz_t; + +typedef struct { + fxrgb_t c; + fxpoint_t p; + zfix32_t z; + } fxpointrgbz_t; + +/* Macros to convert between integer and 32 bit fixed point format */ + +#define MGL_FIX_1 0x10000L +#define MGL_FIX_2 0x20000L +#define MGL_FIX_HALF 0x08000L +#define MGL_TOFIX(i) ((long)(i) << 16) +#define MGL_FIXTOINT(f) ((m_int)((f) >> 16)) +#define MGL_FIXROUND(f) ((m_int)(((f) + MGL_FIX_HALF) >> 16)) + +#define MGL_ZFIX_1 0x10000000L +#define MGL_ZFIX_HALF 0x08000000L +#define MGL_FIXTOZ(i) ((i) << 12) +#define MGL_ZTOFIX(i) ((i) >> 12) +#define MGL_TOZFIX(i) ((long)(i) << 28) +#define MGL_ZFIXTOINT(f) ((m_int)((f) >> 28)) +#define MGL_ZFIXROUND(f) ((m_int)(((f) + MGL_ZFIX_HALF) >> 28)) + +/* Region structure */ + +#ifdef BUILD_MGL +struct _span_t; +typedef struct _span_t span_t; +#else +typedef void span_t; +#endif + +typedef struct { + rect_t rect; /* Bounding rectangle for region */ + span_t *spans; /* Start of span list for region */ + } region_t; + +/* Palette entry structure */ + +typedef struct { + uchar blue; /* Blue component of color */ + uchar green; /* Green component of color */ + uchar red; /* Blue component of color */ + uchar alpha; /* Alpha or alignment byte */ + } palette_t; + +/* Maximum value for each palette entry component */ + +#define PALMAX 255 /* Max value for palette components */ + +/* Pixel format structure */ + +typedef struct { + uchar redMask,greenMask; /* Mask values for pixels */ + uchar blueMask,rsvdMask; + m_int redPos,redAdjust; /* Red position and adjustment */ + m_int greenPos,greenAdjust; /* Green position and adjustment */ + m_int bluePos,blueAdjust; /* Blue position and adjustment */ + m_int rsvdPos,rsvdAdjust; /* Reserved position and adjustment */ + } pixel_format_t; + +/* Structure to hold arc coordinate information */ + +typedef struct { + m_int x,y; /* Centre point of the arc */ + m_int startX,startY; /* Starting point on arc */ + m_int endX,endY; /* Ending point on arc */ + } arc_coords_t; + +/* Mouse cursor structure */ + +typedef struct { + ulong xorMask[32]; + ulong andMask[32]; + m_int xHotSpot; + m_int yHotSpot; + } cursor_t; + +/* Bitmap structure - always packed pixel DIB format */ + +typedef struct { + m_int width; /* Width of bitmap in pixels */ + m_int height; /* Height of bitmap in pixels */ + m_int bitsPerPixel; /* Pixel width */ + m_int bytesPerLine; /* Bytes per line value for surface */ + uchar *surface; /* Pointer to bitmap surface */ + palette_t *pal; /* Palette (NULL if not loaded) */ + pixel_format_t *pf; /* Pixel format (NULL if none) */ + + /* ... palette, pixel format and bitmap data are store contiguously */ + } bitmap_t; + +/* Icon structure - can be 32x23, 64x64 or in fact any size */ + +typedef struct { + m_int byteWidth; /* Byte with for AND mask */ + uchar *andMask; /* Hold punch mask for icon */ + bitmap_t xorMask; /* XOR mask for the icon */ + + /* ... AND mask and bitmap structure are stored contiguously */ + } icon_t; + +/* Default cursor name */ + +#define MGL_DEF_CURSOR _MGL_getDefCursor() + +/* Generic Font structure */ + +#define _MGL_FNAMESIZE 58 + +typedef struct { + char name[_MGL_FNAMESIZE];/* Name of the font */ + short fontType; /* Type of font */ + short maxWidth; /* Maximum character width */ + short maxKern; /* Maximum character kern */ + short fontWidth; /* Font width */ + short fontHeight; /* Font height */ + short ascent; /* Font ascent value */ + short descent; /* Font descent value */ + short leading; /* Font leading value */ + } font_t; + +/* Character and font metrics structure */ + +typedef struct { + m_int width; /* Width of character or font */ + m_int fontWidth; /* Character width (tightest fit) */ + m_int fontHeight; /* Height of the font */ + m_int ascent; /* Ascent value */ + m_int descent; /* Descent value */ + m_int leading; /* Leading value */ + m_int kern; /* Kern value */ + } metrics_t; + +/* Text settings structure */ + +typedef struct { + m_int horizJust; /* Horizontal justfication */ + m_int vertJust; /* Vertical justification */ + m_int dir; /* Text drawing direction */ + m_int szNumerx; /* Text x size numerator */ + m_int szNumery; /* Text y size numerator */ + m_int szDenomx; /* Text x size denominator */ + m_int szDenomy; /* Text y size denominator */ + m_int spaceExtra; /* Space extra term */ + font_t *font; /* Currently selected font */ + } text_settings_t; + +/* Macros to access the (left,top) and (right,bottom) points of a + * rectangle. + */ + +#define MGL_leftTop(r) (((point_t *) &(r))[0]) +#define MGL_rightBottom(r) (((point_t *) &(r))[1]) + +typedef uchar pattern_t[8]; +typedef color_t pixpattern_t[8][8]; + +/* Attributes structure */ + +typedef struct { + color_t color; /* Foreground color */ + color_t backColor; /* Background color */ + m_int colorMode; /* Current color mode */ + m_int markerSize; /* Size of markers in pixels */ + m_int markerStyle; /* Style of markers */ + color_t markerColor; /* Color to draw markers in */ + color_t bdrBright; /* Border bright color */ + color_t bdrDark; /* Border dark color */ + point_t CP; /* Graphics pen position */ + m_int writeMode; /* Scan conversion write mode op. */ + m_int penStyle; /* Pen style */ + m_int penHeight; /* Height of pen */ + m_int penWidth; /* Width of pen */ + pattern_t penPat; /* Pattern for pen */ + pixpattern_t penPixPat; /* Pixmap pattern for pen */ + m_int lineStyle; /* Line style */ + ushort lineStipple; /* Line stipple */ + m_uint stippleCount; /* Current line stipple count */ + rect_t viewPort; /* Viewport dimensions */ + point_t viewPortOrg; /* Logical viewport origin */ + rect_t clipRect; /* Clipping rectangle dimensions */ + m_int clip; /* Is clipping on? */ + m_int polyType; /* Polygon drawing type */ + text_settings_t ts; /* Text drawing attributes */ + } attributes_t; + +/* Mode specific format information. This structrure can be used by + * the device driver to build tables of values for all supported modes + */ + +typedef struct { + m_int xRes; /* Device x resolution - 1 */ + m_int yRes; /* Device y resolution - 1 */ + m_int bitsPerPixel; /* Number of bits per pixel */ + m_int numberOfPlanes; /* Number of planes in image */ + color_t maxColor; /* Maximum number of colors - 1 */ + m_int maxPage; /* Maximum number of video pages - 1 */ + m_int bytesPerLine; /* Number of bytes in a line */ + m_int aspectRatio; /* Mode aspect ratio (horiz/vert * 1000) */ + long pageSize; /* Number of bytes in a page */ + m_int scratch1; /* Scratch pad value 1 */ + m_int scratch2; /* Scratch pad value 2 */ + char redMaskSize; /* Size of direct color red mask */ + char redFieldPosition; /* Bit posn of lsb of red mask */ + char greenMaskSize; /* Size of direct color green mask */ + char greenFieldPosition; /* Bit posn of lsb of green mask */ + char blueMaskSize; /* Size of direct color blue mask */ + char blueFieldPosition; /* Bit posn of lsb of blue mask */ + char rsvdMaskSize; /* Size of reserved mask */ + char rsvdFieldPosition; /* Bit posn of reserved mask */ + } gmode_t; + +/* Public Device Context Structure. The 'surface' member along with the + * gmode_t information block, provides direct access to the active + * display surface for user applications. The MGL virtualises the surface + * in SuperVGA modes that dont have a real linear framebuffer. + */ + +typedef struct { + attributes_t a; /* Active device attributes */ + void *surface; /* Pointer to active device surface */ + void *zbuffer; /* Pointer to Z-buffer if allocated */ + m_int zbits; /* Bits per zbuffer element */ + m_int zwidth; /* Width of the zbuffer in pixels */ + gmode_t mi; /* Mode specific information block */ + pixel_format_t pf; /* Current pixel format for device context */ + color_t *colorTab; /* Color lookup table cache */ + color_t *shadeTab; /* Currently active shade table */ + m_int bankOffset; /* Offset of starting bank number */ + + /* Remainder of Device Context structure is private and internal */ + } publicDevCtx_t; + +#ifndef BUILD_MGL +typedef publicDevCtx_t MGLDC; +#else +struct internalDevCtx_t; +typedef struct internalDevCtx_t MGLDC; +#endif + +typedef struct { + ulong which; /* Which window for window manager code */ + m_uint what; /* Event code */ + ulong when; /* Clock ticks since midnight */ + m_int where_x; /* Mouse location */ + m_int where_y; + ulong message; /* Event specific message */ + ulong modifiers; /* Modifier flags */ + m_int next; /* Next event in queue */ + m_int prev; /* Previous event in queue */ + } event_t; + +/* Structure containing file I/O functions allowing the user application to + * completely replace the MGL's file I/O functions with their own. This + * allows the app to store all MGL related files in a single large file, + * with encryption or compression is desired. By default normal file I/O + * functions will be used. + */ + +typedef struct { + FILE * (*fopen)(const char *filename,const char *mode); + int (*fclose)(FILE *f); + int (*fseek)(FILE *f,long offset,int whence); + long (*ftell)(FILE *f); + size_t (*fread)(void *ptr,size_t size,size_t n,FILE *f); + size_t (*fwrite)(const void *ptr,size_t size,size_t n,FILE *f); + } fileio_t; + +/* Define the flags for the types of direct surface access provided */ + +#define MGL_NO_ACCESS 0x0 /* Surface cannot be accessed */ +#define MGL_VIRTUAL_ACCESS 0x1 /* Surface is virtualised */ +#define MGL_LINEAR_ACCESS 0x2 /* Surface can be linearly accessed */ +#define MGL_SURFACE_FLAGS 0x3 + +/* Define the flags for the types of direct zbuffer access provided */ + +#define MGL_NO_ZACCESS 0x0 /* Zbuffer cannot be accessed */ +#define MGL_VIRTUAL_ZACCESS 0x4 /* Zbuffer is virtualised in */ +#define MGL_LINEAR_ZACCESS 0x8 /* Zbuffer can be linearly accessed */ +#define MGL_ZBUFFER_FLAGS 0xC + +/* Define the flags for the types of hardware acceleration supported by + * the device context. This will allow the application to tailor the use of + * MGL functions depending upon whether specific hardware support is + * available. Hence applications can use specialised software rendering + * support if the desired hardware support is not available. + * + * NOTE: If the hardware flags are not MGL_HW_NONE, you *must* call + * the MGL_beginDirectAccess() and MGL_endDirectAccess() functions + * before and after any custom code that does direct framebuffer + * rendering!! + * + * This is not necessary for non-accelerated device context, so you + * might want to optimise these calls out if there is no hardware + * acceleration support. + */ + +#define MGL_HW_NONE 0x0000 /* No hardware acceleration */ +#define MGL_HW_LINE 0x0010 /* Hardware line drawing */ +#define MGL_HW_STIPPLE_LINE 0x0020 /* Hardware stippled line drawing */ +#define MGL_HW_POLY 0x0040 /* Hardware polygon filling */ +#define MGL_HW_RECT 0x0080 /* Hardware rectangle fill */ +#define MGL_HW_PATT_RECT 0x0100 /* Hardware pattern rectangle fill */ +#define MGL_HW_CLRPATT_RECT 0x0200 /* Hardware color pattern fill */ +#define MGL_HW_SCR_BLT 0x0400 /* Hardware screen/screen bitBlt */ +#define MGL_HW_SRCTRANS_BLT 0x0800 /* Hardware source transparent blt */ +#define MGL_HW_DSTTRANS_BLT 0x1000 /* Hardware dest. transparent blt */ +#define MGL_HW_MONO_BLT 0x2000 /* Hardware monochrome blt */ +#define MGL_HW_CLIP 0x4000 /* Hardware clipping */ +#define MGL_HW_FLAGS 0xFFF0 + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/*------------------------- Function Prototypes ---------------------------*/ + +/*--------------------------------------------------------------------------- + * Routines bound to a specific device context. These routines all take + * an MGLDC as a parmeter for the context to work with and hence dont work + * with the current context. If however the context passed is the currently + * active context, all changes to that context are reflected in the + * currently active context as well. + *-------------------------------------------------------------------------*/ + +/* Environment detection and initialisation */ + +m_int MGLAPI MGL_registerDriver(const char *name,void *driver); +void MGLAPI MGL_unregisterAllDrivers(void); +void MGLAPI MGL_registerAllDispDrivers(bool useLinear,bool useDirectDraw,bool useWinDirect); +void MGLAPI MGL_registerAllMemDrivers(void); +void MGLAPI MGL_detectGraph(m_int *driver,m_int *mode); +uchar * MGLAPI MGL_availableModes(void); +m_int MGLAPI MGL_availablePages(m_int mode); +m_int MGLAPI MGL_modeResolution(m_int mode,m_int *xRes,m_int *yRes,m_int *bitsPerPixel); +bool MGLAPI MGL_isDisplayDC(MGLDC *dc); +bool MGLAPI MGL_isWindowedDC(MGLDC *dc); +bool MGLAPI MGL_isMemoryDC(MGLDC *dc); +void MGLAPI MGL_exit(void); +void MGLAPI MGL_setBufSize(unsigned size); +void MGLAPI MGL_fatalError(const char *msg); +m_int MGLAPI MGL_result(void); +void MGLAPI MGL_setResult(m_int result); +const char * MGLAPI MGL_errorMsg(m_int err); +const char * MGLAPI MGL_modeName(m_int mode); +const char * MGLAPI MGL_modeDriverName(m_int mode); +const char * MGLAPI MGL_driverName(m_int driver); +m_int MGLAPI MGL_getDriver(MGLDC *dc); +m_int MGLAPI MGL_getMode(MGLDC *dc); +m_int MGLAPI MGL_surfaceAccessType(MGLDC *dc); +m_int MGLAPI MGL_zbufferAccessType(MGLDC *dc); +long MGLAPI MGL_getHardwareFlags(MGLDC *dc); +void MGLAPI MGL_defaultAttributes(MGLDC *dc); +void MGLAPI MGL_makeSubDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom); + +/* Viewport and clip rectangle manipulation bound to a specific DC */ + +void MGLAPI MGL_setViewportDC(MGLDC *dc,rect_t view); +void MGLAPI MGL_setRelViewportDC(MGLDC *dc,rect_t view); +void MGLAPI MGL_getViewportDC(MGLDC *dc,rect_t *view); +void MGLAPI MGL_setViewportOrgDC(MGLDC *dc,point_t org); +void MGLAPI MGL_getViewportOrgDC(MGLDC *dc,point_t *org); +void MGLAPI MGL_globalToLocalDC(MGLDC *dc,point_t *p); +void MGLAPI MGL_localToGlobalDC(MGLDC *dc,point_t *p); +m_int MGLAPI MGL_maxxDC(MGLDC *dc); +m_int MGLAPI MGL_maxyDC(MGLDC *dc); +void MGLAPI MGL_setClipRectDC(MGLDC *dc,rect_t clip); +void MGLAPI MGL_getClipRectDC(MGLDC *dc,rect_t *clip); +void MGLAPI MGL_setClipModeDC(MGLDC *dc,bool mode); +bool MGLAPI MGL_getClipModeDC(MGLDC *dc); + +/* Color and palette manipulation */ + +color_t MGLAPI MGL_realColor(MGLDC *dc,m_int color); +color_t MGLAPI MGL_rgbColor(MGLDC *dc,uchar R,uchar G,uchar B); +void MGLAPI MGL_setPaletteEntry(MGLDC *dc,m_int entry,uchar red,uchar green,uchar blue); +void MGLAPI MGL_getPaletteEntry(MGLDC *dc,m_int entry,uchar *red,uchar *green,uchar *blue); +void MGLAPI MGL_setPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex); +void MGLAPI MGL_getPalette(MGLDC *dc,palette_t *pal,m_int numColors,m_int startIndex); +void ASMAPI MGL_rotatePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int direction); +bool ASMAPI MGL_fadePalette(MGLDC *dc,palette_t *fullIntensity,m_int numColors,m_int startIndex,uchar intensity); +void MGLAPI MGL_realizePalette(MGLDC *dc,m_int numColors,m_int startIndex,m_int waitVRT); +m_int MGLAPI MGL_getPaletteSize(MGLDC *dc); +void MGLAPI MGL_getDefaultPalette(MGLDC *dc,palette_t *pal); +void MGLAPI MGL_setDefaultPalette(MGLDC *dc); +#ifndef MGL_LITE +bool MGLAPI MGL_checkIdentityPalette(bool enable); +void MGLAPI MGL_mapToPalette(MGLDC *dc,palette_t *pal); +#endif + +/* Generic device context information and manipulation */ + +bool MGLAPI MGL_haveWidePalette(MGLDC *dc); +m_int MGLAPI MGL_getBitsPerPixel(MGLDC *dc); +color_t MGLAPI MGL_maxColor(MGLDC *dc); +m_int MGLAPI MGL_maxPage(MGLDC *dc); +m_int MGLAPI MGL_sizex(MGLDC *dc); +m_int MGLAPI MGL_sizey(MGLDC *dc); +void MGLAPI MGL_getPixelFormat(MGLDC *dc,pixel_format_t *pf); +void * MGLAPI MGL_computePixelAddr(MGLDC *dc,int x,int y); + +/* Double buffering support */ + +void MGLAPI MGL_setActivePage(MGLDC *dc,m_int page); +m_int MGLAPI MGL_getActivePage(MGLDC *dc); +void MGLAPI MGL_setVisualPage(MGLDC *dc,m_int page,m_int waitVRT); +m_int MGLAPI MGL_getVisualPage(MGLDC *dc); +void MGLAPI MGL_setDisplayStart(MGLDC *dc,m_int x,m_int y,m_int waitFlag); +void MGLAPI MGL_getDisplayStart(MGLDC *dc,m_int *x,m_int *y); +void MGLAPI MGL_vSync(MGLDC *dc); +bool MGLAPI MGL_doubleBuffer(MGLDC *dc); +void MGLAPI MGL_singleBuffer(MGLDC *dc); +void MGLAPI MGL_swapBuffers(MGLDC *dc,m_int waitVRT); + +/* Zbuffering support */ + +#ifdef MGL_3D +m_int MGLAPI MGL_getHardwareZBufferDepth(MGLDC *dc); +bool ASMAPI MGL_zBegin(MGLDC *dc,m_int zbits); +bool MGLAPI MGL_zShareZBuffer(MGLDC *dc,MGLDC *dcShared,m_int zbits); +#endif + +/* Event handling support */ + +bool MGLAPI EVT_getNext(event_t *evt,m_uint mask); +bool MGLAPI EVT_peekNext(event_t *evt,m_uint mask); +bool MGLAPI EVT_post(ulong which,m_uint what,ulong message,ulong modifiers); +void MGLAPI EVT_flush(m_uint mask); +void MGLAPI EVT_halt(event_t *evt,m_uint mask); +m_int MGLAPI EVT_setTimerTick(m_int ticks); + +/*--------------------------------------------------------------------------- + * Routines bound to the currently active context. All these routines work + * with the currently active context and do not reflect any changes made + * to the global context to the original user supplied context (because it + * may be cached). The cached DC is automatically flushed back to the + * original DC when a new context is enabled with MGL_makeCurrentDC(). + * + * Before destroying a DC that is current, make sure you call + * MGL_makeCurrentDC(NULL) first! + *-------------------------------------------------------------------------*/ + +/* Routines to change the active global device context */ + +MGLDC * MGLAPI MGL_makeCurrentDC(MGLDC *dc); +bool MGLAPI MGL_isCurrentDC(MGLDC *dc); + +/* Current device context information and manipulation */ + +m_int MGLAPI MGL_getAspectRatio(void); +void MGLAPI MGL_setAspectRatio(m_int aspectRatio); +void ASMAPI MGL_setColor(color_t color); +void MGLAPI MGL_setColorRGB(uchar R,uchar G,uchar B); +void MGLAPI MGL_setColorCI(m_int index); +color_t MGLAPI MGL_getColor(void); +void ASMAPI MGL_setBackColor(color_t color); +color_t MGLAPI MGL_getBackColor(void); +color_t ASMAPI MGL_packColor(pixel_format_t *pf,uchar R,uchar G,uchar B); +void MGLAPI MGL_unpackColor(pixel_format_t *pf,color_t color,uchar *R,uchar *G,uchar *B); +color_t ASMAPI MGL_packColorRGB(uchar R,uchar G,uchar B); +void MGLAPI MGL_unpackColorRGB(color_t color,uchar *R,uchar *G,uchar *B); +color_t MGLAPI MGL_defaultColor(void); +#ifndef MGL_LITE +void MGLAPI MGL_setMarkerSize(m_int size); +m_int MGLAPI MGL_getMarkerSize(void); +void MGLAPI MGL_setMarkerStyle(m_int style); +m_int MGLAPI MGL_getMarkerStyle(void); +void MGLAPI MGL_setMarkerColor(color_t color); +color_t MGLAPI MGL_getMarkerColor(void); +void MGLAPI MGL_setBorderColors(color_t bright,color_t dark); +void MGLAPI MGL_getBorderColors(color_t *bright,color_t *dark); +void ASMAPI MGL_setWriteMode(m_int mode); +m_int MGLAPI MGL_getWriteMode(void); +void ASMAPI MGL_setPenStyle(m_int style); +m_int MGLAPI MGL_getPenStyle(void); +void MGLAPI MGL_setLineStyle(m_int style); +m_int MGLAPI MGL_getLineStyle(void); +void ASMAPI MGL_setLineStipple(ushort stipple); +ushort MGLAPI MGL_getLineStipple(void); +void ASMAPI MGL_setLineStippleCount(m_uint stippleCount); +m_uint MGLAPI MGL_getLineStippleCount(void); +void ASMAPI MGL_setPenBitmapPattern(const pattern_t *pat); +void MGLAPI MGL_getPenBitmapPattern(pattern_t *pat); +void ASMAPI MGL_setPenPixmapPattern(const pixpattern_t *pat); +void MGLAPI MGL_getPenPixmapPattern(pixpattern_t *pat); +void MGLAPI MGL_setPenSize(m_int height,m_int width); +void MGLAPI MGL_getPenSize(m_int *height,m_int *width); +#ifndef MGL_LITE +void MGLAPI MGL_setColorMapMode(m_int mode); +m_int MGLAPI MGL_getColorMapMode(void); +#endif +void MGLAPI MGL_setPolygonType(m_int type); +m_int MGLAPI MGL_getPolygonType(void); +#endif +void MGLAPI MGL_getAttributes(attributes_t *attr); +void MGLAPI MGL_restoreAttributes(attributes_t *attr); + +/* Device clearing */ + +void ASMAPI MGL_clearDevice(void); +void MGLAPI MGL_clearViewport(void); + +/* Viewport and clip rectangle manipulation */ + +void MGLAPI MGL_setViewport(rect_t view); +void MGLAPI MGL_setRelViewport(rect_t view); +void MGLAPI MGL_getViewport(rect_t *view); +void MGLAPI MGL_setViewportOrg(point_t org); +void MGLAPI MGL_getViewportOrg(point_t *org); +void MGLAPI MGL_globalToLocal(point_t *p); +void MGLAPI MGL_localToGlobal(point_t *p); +m_int MGLAPI MGL_maxx(void); +m_int MGLAPI MGL_maxy(void); +void MGLAPI MGL_setClipRect(rect_t clip); +void MGLAPI MGL_getClipRect(rect_t *clip); +void MGLAPI MGL_setClipMode(bool mode); +bool MGLAPI MGL_getClipMode(void); + +/* Pixel plotting */ + +void MGLAPI MGL_pixelCoord(m_int x,m_int y); +color_t MGLAPI MGL_getPixelCoord(m_int x,m_int y); +void ASMAPI MGL_beginPixel(void); +void MGLAPI MGL_pixelCoordFast(m_int x,m_int y); +color_t MGLAPI MGL_getPixelCoordFast(m_int x,m_int y); +void ASMAPI MGL_endPixel(void); + +/* Line drawing and clipping */ + +void MGLAPI MGL_moveToCoord(m_int x,m_int y); +void MGLAPI MGL_moveRelCoord(m_int dx,m_int dy); +void MGLAPI MGL_lineToCoord(m_int x,m_int y); +void MGLAPI MGL_lineRelCoord(m_int dx,m_int dy); +m_int MGLAPI MGL_getX(void); +m_int MGLAPI MGL_getY(void); +void MGLAPI MGL_getCP(point_t* CP); +void MGLAPI MGL_lineCoord(m_int x1,m_int y1,m_int x2,m_int y2); +void MGLAPI MGL_lineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2); +void MGLAPI MGL_lineCoordFast(m_int x1,m_int y1,m_int x2,m_int y2); +void MGLAPI MGL_lineCoordFastFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2); +void MGLAPI MGL_lineEngine(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,void (ASMAPI *plotPoint)(m_int x,m_int y)); +bool MGLAPI MGL_clipLineFX(fix32_t *x1,fix32_t *y1,fix32_t *x2,fix32_t *y2,fix32_t left,fix32_t top,fix32_t right,fix32_t bottom); +#ifndef MGL_LITE +void ASMAPI MGL_scanLine(m_int y,m_int x1,m_int x2); +#endif + +/* Routines to perform bank switching for banked framebuffers for custom + * rendering code. The first version is callable only from assembler and + * requires the new bank value to be passed in the DL register. The second + * version is callable directly from C. DO NOT CALL THESE FUNCTIONS WHEN + * RUNNING WITH A LINEAR FRAMEBUFFER!!! + */ + +void _ASMAPI SVGA_setBank(void); +void _ASMAPI SVGA_setBankC(int bank); + +/* Routines to begin/end direct framebuffer access. You must call these + * functions is you wish to render directly to a hardware accelerated + * device surface. + */ + +void ASMAPI MGL_beginDirectAccess(void); +void ASMAPI MGL_endDirectAccess(void); + +/* Routines to begin/end fast rendering of flat shaded lines, scanlines + * and polygons. + */ + +void ASMAPI MGL_beginDrawing(void); +void ASMAPI MGL_endDrawing(void); + +/* Routines to begin/end fast rendering of smooth shaded lines, scanlines + * and polygons. + */ + +#ifdef MGL_3D +void ASMAPI MGL_beginShadedDrawing(void); +void ASMAPI MGL_endShadedDrawing(void); +#endif + +/* Routines to begin/end fast rendering of flat shaded, zbuffered lines and + * polygons. + */ + +#ifdef MGL_3D +void ASMAPI MGL_beginZDrawing(void); +void ASMAPI MGL_endZDrawing(void); +#endif + +/* Routines to begin/end fast rendering of smooth shaded, zbuffered lines and + * polygons. + */ + +#ifdef MGL_3D +void ASMAPI MGL_beginZShadedDrawing(void); +void ASMAPI MGL_endZShadedDrawing(void); +#endif + +/* Polygon drawing: Note that the following fast polygon routines + * only work with convex polygons. The integer coordinate versions are + * provided for compatibility only, and convert the coordinates to fixed + * point and call the appropriate fixed point routines below. + */ + +#ifndef MGL_LITE +void MGLAPI MGL_fillPolygon(m_int count,point_t *vArray,m_int xOffset,m_int yOffset); +void MGLAPI MGL_fillPolygonFast(m_int count,point_t *vArray,m_int xOffset,m_int yOffset); +void ASMAPI MGL_fillPolygonFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_fillPolygonFastFX(m_int count,fxpoint_t *vArray,m_int vinc,fix32_t xOffset,fix32_t yOffset); +#endif + +/* 3D rasterization routines */ + +#ifdef MGL_3D +void MGLAPI MGL_zClearCoord(m_int left,m_int top,m_int right,m_int bottom,zfix32_t clearVal); +#endif + +#ifdef MGL_FIX3D +void ASMAPI MGL_cLineCoordFast(fix32_t x1,fix32_t y1,fix32_t c1,fix32_t x2,fix32_t y2,fix32_t c2); +void ASMAPI MGL_rgbLineCoordFast(fix32_t x1,fix32_t y1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,fix32_t r2,fix32_t g2,fix32_t b2); +void ASMAPI MGL_zLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t x2,fix32_t y2,zfix32_t z2); +void ASMAPI MGL_czLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t c1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t c2); +void ASMAPI MGL_rgbzLineCoordFast(fix32_t x1,fix32_t y1,zfix32_t z1,fix32_t r1,fix32_t g1,fix32_t b1,fix32_t x2,fix32_t y2,zfix32_t z2,fix32_t r2,fix32_t g2,fix32_t b2); + +void ASMAPI MGL_triFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_cTriFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_rgbTriFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_zTriFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); +void ASMAPI MGL_czTriFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); +void ASMAPI MGL_rgbzTriFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); + +void ASMAPI MGL_quadFast(fxpoint_t *v1,fxpoint_t *v2,fxpoint_t *v3,fxpoint_t *v4,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_cQuadFast(fxpointc_t *v1,fxpointc_t *v2,fxpointc_t *v3,fxpointc_t *v4,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_rgbQuadFast(fxpointrgb_t *v1,fxpointrgb_t *v2,fxpointrgb_t *v3,fxpointrgb_t *v4,fix32_t xOffset,fix32_t yOffset); +void ASMAPI MGL_zQuadFast(fxpointz_t *v1,fxpointz_t *v2,fxpointz_t *v3,fxpointz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); +void ASMAPI MGL_czQuadFast(fxpointcz_t *v1,fxpointcz_t *v2,fxpointcz_t *v3,fxpointcz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); +void ASMAPI MGL_rgbzQuadFast(fxpointrgbz_t *v1,fxpointrgbz_t *v2,fxpointrgbz_t *v3,fxpointrgbz_t *v4,fix32_t xOffset,fix32_t yOffset,zfix32_t zOffset); +#endif + +/* Routine to set the currently active shade table. In HiColor and TrueColor + * video modes, you must set a valid shadeTable before you call any of the + * color index shaded rendering routines (MGL_cTri() etc). These routines + * will interpolate an index into the current shade table rather than + * each of the RGB color channels, and the appropriate full RGB color is + * extracted directly from the shade table. The shade table can be any size, + * but the application must ensure that the indices passed in are within + * the range of the current shade table. + */ + +#ifdef MGL_3D +void MGLAPI MGL_setShadeTable(color_t *shadeTab); +#endif + +/* Polyline drawing */ + +#ifndef MGL_LITE +void MGLAPI MGL_marker(point_t p); +void MGLAPI MGL_polyPoint(m_int count,point_t *vArray); +void MGLAPI MGL_polyMarker(m_int count,point_t *vArray); +void MGLAPI MGL_polyLine(m_int count,point_t *vArray); +#endif + +/* Rectangle drawing */ + +#ifndef MGL_LITE +void MGLAPI MGL_rectCoord(m_int left,m_int top,m_int right,m_int bottom); +void MGLAPI MGL_fillRectCoord(m_int left,m_int top,m_int right,m_int bottom); +#endif + +/* Scanline color scanning. Thee routines are primitive, and do not perform + * any clipping or viewport mapping, so can be used to build you own + * high performance floodfilling routines (see the example file ffill.c + * for pre-built high speed floodfill routines). + */ + +#ifndef MGL_LITE +m_int ASMAPI MGL_scanRightForColor(m_int x,m_int y,color_t color); +m_int ASMAPI MGL_scanLeftForColor(m_int x,m_int y,color_t color); +m_int ASMAPI MGL_scanRightWhileColor(m_int x,m_int y,color_t color); +m_int ASMAPI MGL_scanLeftWhileColor(m_int x,m_int y,color_t color); +#endif + +/* Psuedo 3D border drawing */ + +#ifndef MGL_LITE +void MGLAPI MGL_drawBorderCoord(m_int left,m_int top,m_int right,m_int bottom,m_int style,m_int thickness); +void MGLAPI MGL_drawHDivider(m_int y,m_int x1,m_int x2); +void MGLAPI MGL_drawVDivider(m_int x,m_int y1,m_int y2); +#endif + +/* Ellipse drawing */ + +#ifndef MGL_LITE +void MGLAPI MGL_ellipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); +void MGLAPI MGL_ellipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle); +void ASMAPI MGL_getArcCoords(arc_coords_t *coords); +void MGLAPI MGL_ellipse(rect_t extentRect); +void MGLAPI MGL_ellipseCoord(m_int x,m_int y,m_int xradius,m_int yradius); +void MGLAPI MGL_fillEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); +void MGLAPI MGL_fillEllipseArcCoord(m_int x,m_int y,m_int xradius,m_int yradius,m_int startAngle,m_int endAngle); +void MGLAPI MGL_fillEllipse(rect_t extentRect); +void MGLAPI MGL_fillEllipseCoord(m_int x,m_int y,m_int xradius,m_int yradius); +void MGLAPI MGL_ellipseEngine(rect_t extentRect,void (ASMAPI *setup)(m_int topY,m_int botY,m_int left,m_int right),void (ASMAPI *set4pixels)(bool inc_x,bool inc_y,bool region1),void (ASMAPI *finished)(void)); +void MGLAPI MGL_ellipseArcEngine(rect_t extentRect,m_int startAngle,m_int endAngle,arc_coords_t *ac,void (ASMAPI *plotPoint)(m_int x,m_int y)); +#endif + +/* Text attribute manipulation */ + +#ifndef MGL_LITE +void MGLAPI MGL_setTextJustify(m_int horiz,m_int vert); +void MGLAPI MGL_getTextJustify(m_int *horiz,m_int *vert); +void MGLAPI MGL_setTextDirection(m_int direction); +m_int MGLAPI MGL_getTextDirection(void); +void MGLAPI MGL_setTextSize(m_int numerx,m_int denomx,m_int numery,m_int denomy); +void MGLAPI MGL_getTextSize(m_int *numerx,m_int *denomx,m_int *numery,m_int *denomy); +void MGLAPI MGL_setSpaceExtra(m_int extra); +m_int MGLAPI MGL_getSpaceExtra(void); +void MGLAPI MGL_setTextSettings(text_settings_t *settings); +void MGLAPI MGL_getTextSettings(text_settings_t *settings); +m_int MGLAPI MGL_textHeight(void); +m_int MGLAPI MGL_textWidth(const char *str); +void MGLAPI MGL_textBounds(m_int x,m_int y,const char *str,rect_t *bounds); +m_int MGLAPI MGL_charWidth(char ch); +void MGLAPI MGL_getFontMetrics(metrics_t *metrics); +void MGLAPI MGL_getCharMetrics(char ch,metrics_t *metrics); +m_int MGLAPI MGL_maxCharWidth(void); +void MGLAPI MGL_underScoreLocation(m_int *x,m_int *y,const char *str); +#endif + +/* Text drawing */ + +#ifndef MGL_LITE +void MGLAPI MGL_drawStr(const char *str); +void MGLAPI MGL_drawStrXY(m_int x,m_int y,const char *str); +bool MGLAPI MGL_useFont(font_t *font); +font_t * MGLAPI MGL_getFont(void); +bool MGLAPI MGL_vecFontEngine(m_int x,m_int y,const char *str,void (ASMAPI *move)(m_int x,m_int y),void (ASMAPI *draw)(m_int x,m_int y)); +#endif + +/* BitBlt support */ + +void MGLAPI MGL_bitBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int op); +void MGLAPI MGL_stretchBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom); +#ifndef MGL_LITE +void MGLAPI MGL_getDivotCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,void *divot); +void MGLAPI MGL_putDivot(MGLDC *dc,void *divot); +long MGLAPI MGL_divotSizeCoord(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom); +void MGLAPI MGL_putMonoImage(MGLDC *dc,m_int x,m_int y,m_int byteWidth,m_int height,void *image); +void MGLAPI MGL_putBitmap(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,m_int op); +void MGLAPI MGL_putBitmapSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,m_int op); +void MGLAPI MGL_putBitmapTransparent(MGLDC *dc,m_int x,m_int y,const bitmap_t *bitmap,color_t transparent,bool sourceTrans); +void MGLAPI MGL_putBitmapTransparentSection(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,const bitmap_t *bitmap,color_t transparent,bool sourceTrans); +void MGLAPI MGL_putBitmapMask(MGLDC *dc,m_int x,m_int y,const bitmap_t *mask,color_t color); +void MGLAPI MGL_stretchBitmap(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,const bitmap_t *bitmap); +void MGLAPI MGL_putIcon(MGLDC *dc,m_int x,m_int y,const icon_t *icon); +void MGLAPI MGL_transBltCoord(MGLDC *dst,MGLDC *src,m_int left,m_int top,m_int right,m_int bottom,m_int dstLeft,m_int dstTop,color_t transparent,bool sourceTrans); +#endif + +/* Linear offscreen DC BitBlt support */ + +#ifndef MGL_LITE +void MGLAPI MGL_bitBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,m_int op); +void MGLAPI MGL_transBltLinCoord(MGLDC *dst,MGLDC *src,ulong srcOfs,m_int dstLeft,m_int dstTop,m_int dstRight,m_int dstBottom,color_t transparent,bool sourceTrans); +#endif + +/* Monochrome bitmap manipulation */ + +#ifndef MGL_LITE +void MGLAPI MGL_drawGlyph(font_t *g,m_int x,m_int y,uchar glyph); +m_int MGLAPI MGL_getGlyphWidth(font_t *font,uchar glyph); +m_int MGLAPI MGL_getGlyphHeight(font_t *font); +void MGLAPI MGL_rotateGlyph(uchar *dst,uchar *src,m_int *byteWidth,m_int *height,m_int rotation); +void MGLAPI MGL_mirrorGlyph(uchar *dst,uchar *src,m_int byteWidth,m_int height); +#endif + +/* Region management */ + +#ifndef MGL_LITE +region_t * MGLAPI MGL_newRegion(void); +region_t * MGLAPI MGL_copyRegion(const region_t *s); +void MGLAPI MGL_clearRegion(region_t *r); +void MGLAPI MGL_freeRegion(region_t *r); +void MGLAPI MGL_drawRegion(m_int x,m_int y,const region_t *r); +#endif + +/* Region generation primitives */ + +#ifndef MGL_LITE +region_t * MGLAPI MGL_rgnLineCoord(m_int x1,m_int y1,m_int x2,m_int y2,const region_t *pen); +region_t * MGLAPI MGL_rgnLineCoordFX(fix32_t x1,fix32_t y1,fix32_t x2,fix32_t y2,const region_t *pen); +/*region_t * MGLAPI MGL_rgnPolygon(m_int count,point_t *vArray);*/ +/*region_t * MGLAPI MGL_rgnPolygonFast(m_int count,point_t *vArray);*/ +region_t * MGLAPI MGL_rgnSolidRectCoord(m_int left,m_int top,m_int right,m_int bottom); +region_t * MGLAPI MGL_rgnEllipse(rect_t extentRect,const region_t *pen); +region_t * MGLAPI MGL_rgnEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle,const region_t *pen); +void MGLAPI MGL_rgnGetArcCoords(arc_coords_t *coords); +region_t * MGLAPI MGL_rgnSolidEllipse(rect_t extentRect); +region_t * MGLAPI MGL_rgnSolidEllipseArc(rect_t extentRect,m_int startAngle,m_int endAngle); +#endif + +/* Region alegbra */ + +#ifndef MGL_LITE +region_t * MGLAPI MGL_sectRegion(const region_t *r1,const region_t *r2); +region_t * MGLAPI MGL_sectRegionRect(const region_t *r1,const rect_t *r2); +bool MGLAPI MGL_unionRegion(region_t *r1,const region_t *r2); +bool MGLAPI MGL_unionRegionRect(region_t *r1,const rect_t *r2); +bool MGLAPI MGL_unionRegionOfs(region_t *r1,const region_t *r2,m_int xOffset,m_int yOffset); +bool MGLAPI MGL_diffRegion(region_t *r1,const region_t *r2); +bool MGLAPI MGL_diffRegionRect(region_t *r1,const rect_t *r2); +void MGLAPI MGL_optimizeRegion(region_t *r); +void MGLAPI MGL_offsetRegion(region_t *r,m_int dx,m_int dy); +bool MGLAPI MGL_emptyRegion(const region_t *r); +bool MGLAPI MGL_equalRegion(const region_t *r1,const region_t *r2); +bool MGLAPI MGL_ptInRegionCoord(m_int x,m_int y,const region_t *r); +#endif + +/* Region traversal */ + +#ifndef MGL_LITE +typedef void (ASMAPI *rgncallback_t)(const rect_t *r); + +void MGLAPI MGL_traverseRegion(region_t *rgn,rgncallback_t doRect); +#endif + +/* RGB to 8 bit halftone dithering routines */ + +#ifndef MGL_LITE +void MGLAPI MGL_getHalfTonePalette(palette_t *pal); +uchar MGLAPI MGL_halfTonePixel(m_int x,m_int y,uchar R,uchar G,uchar B); +#endif + +/* Resource loading/unloading */ + +font_t * MGLAPI MGL_loadFont(const char *fontname); +bool MGLAPI MGL_availableFont(const char *fontname); +void MGLAPI MGL_unloadFont(font_t *font); +cursor_t * MGLAPI MGL_loadCursor(const char *cursorName); +bool MGLAPI MGL_availableCursor(const char *cursorName); +void MGLAPI MGL_unloadCursor(cursor_t *cursor); +#ifndef MGL_LITE +icon_t * MGLAPI MGL_loadIcon(const char *iconName,bool loadPalette); +bool MGLAPI MGL_availableIcon(const char *iconName); +void MGLAPI MGL_unloadIcon(icon_t *icon); +#endif + +/* Windows BMP bitmap loading/unloading/saving */ + +#ifndef MGL_LITE +bitmap_t * MGLAPI MGL_loadBitmap(const char *bitmapName,bool loadPalette); +bool MGLAPI MGL_availableBitmap(const char *bitmapName); +void MGLAPI MGL_unloadBitmap(bitmap_t *bitmap); +bool MGLAPI MGL_getBitmapSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel,pixel_format_t *pf); +bool MGLAPI MGL_loadBitmapIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette); +bool MGLAPI MGL_saveBitmapFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom); +bitmap_t * MGLAPI MGL_getBitmapFromDC(MGLDC *dc,m_int left,m_int top,m_int right,m_int bottom,bool savePalette); +bitmap_t * MGLAPI MGL_buildMonoMask(bitmap_t *bitmap,color_t transparent); +#endif + +/* PCX bitmap loading/unloading/saving (1/4/8 bpp only) */ + +#ifndef MGL_LITE +bitmap_t * MGLAPI MGL_loadPCX(const char *bitmapName,bool loadPalette); +bool MGLAPI MGL_availablePCX(const char *bitmapName); +bool MGLAPI MGL_getPCXSize(const char *bitmapName,m_int *width,m_int *height,m_int *bitsPerPixel); +bool MGLAPI MGL_loadPCXIntoDC(MGLDC *dc,const char *bitmapName,m_int dstLeft,m_int dstTop,bool loadPalette); +bool MGLAPI MGL_savePCXFromDC(MGLDC *dc,const char *bitmapName,m_int left,m_int top,m_int right,m_int bottom); +#endif + +/* Random number generation routines for shorts and longs with full range */ + +void ASMAPI MGL_srand(m_uint seed); +ushort ASMAPI MGL_random(ushort max); +ulong ASMAPI MGL_randoml(ulong max); + +/* Mouse support */ + +bool MGLAPI MS_available(void); +void MGLAPI MS_show(void); +void MGLAPI MS_hide(void); +void MGLAPI MS_obscure(void); +void MGLAPI MS_setCursor(cursor_t *curs); +void MGLAPI MS_setCursorColor(color_t color); +void MGLAPI MS_moveTo(m_int x,m_int y); +void MGLAPI MS_getPos(m_int *x,m_int *y); +void MGLAPI MS_drawCursor(void); + +/* Rectangle and Point manipulation */ + +rect_t MGLAPI MGL_defRect(m_int left,m_int top,m_int right,m_int bottom); +rect_t MGLAPI MGL_defRectPt(point_t leftTop,point_t rightBottom); +bool MGLAPI MGL_sectRect(rect_t s1,rect_t s2,rect_t *d); +bool MGLAPI MGL_sectRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d); +void MGLAPI MGL_unionRect(rect_t s1,rect_t s2,rect_t *d); +void MGLAPI MGL_unionRectCoord(m_int left1,m_int top1,m_int right1,m_int bottom1,m_int left2,m_int top2,m_int right2,m_int bottom2,rect_t *d); + +/* Built-in patterns and mouse cursor */ + +#ifndef MGL_LITE +pattern_t * MGLAPI _MGL_getEmptyPat(void); +pattern_t * MGLAPI _MGL_getGrayPat(void); +pattern_t * MGLAPI _MGL_getSolidPat(void); +#endif +cursor_t * MGLAPI _MGL_getDefCursor(void); + +/* Fixed point multiplication/divide routines */ + +#if defined(__WATCOMC__) && defined(__386__) + +/* For Watcom C++ we can use special inline assembler code that is much + * faster than calling the 386 assembler functions. Currently this is the + * the only compiler that will allow inline assembler to be expanded + * directly as inline functions. + */ + +fix32_t MGL_FixMul(fix32_t a,fix32_t b); +#pragma aux MGL_FixMul = \ + "imul edx" \ + "add eax,8000h" \ + "adc edx,0" \ + "shrd eax,edx,16" \ + parm [eax] [edx] \ + value [eax] \ + modify exact [eax edx]; + +fix32_t MGL_FixDiv(fix32_t a,fix32_t b); +#pragma aux MGL_FixDiv = \ + "xor eax,eax" \ + "shrd eax,edx,16" \ + "sar edx,16" \ + "idiv ebx" \ + parm [edx] [ebx] \ + value [eax] \ + modify exact [eax edx]; + +fix32_t MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c); +#pragma aux MGL_FixMulDiv = \ + "imul ebx" \ + "idiv ecx" \ + parm [eax] [ebx] [ecx] \ + value [eax] \ + modify exact [eax edx]; + +m_int MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2); +#pragma aux MGL_backfacing = \ + "imul ebx" \ + "mov ebx,eax" \ + "mov ecx,edx" \ + "mov eax,esi" \ + "imul edi" \ + "sub eax,ebx" \ + "mov eax,1" \ + "sbb edx,ecx" \ + "jns @@Backfacing" \ + "xor eax,eax" \ + "@@Backfacing:" \ + parm [eax] [esi] [edi] [ebx] \ + value [eax] \ + modify exact [eax ecx edx]; + +void MGL_memcpy(void *dst,void *src,m_int n); +#pragma aux MGL_memcpy = \ + "mov eax,ecx" \ + "shr ecx,2" \ + "rep movsd" \ + "mov cl,al" \ + "and cl,3" \ + "rep movsb" \ + parm [edi] [esi] [ecx] \ + modify exact [eax ecx esi edi]; + +#else + +fix32_t ASMAPI MGL_FixMul(fix32_t a,fix32_t b); +fix32_t ASMAPI MGL_FixDiv(fix32_t a,fix32_t b); +fix32_t ASMAPI MGL_FixMulDiv(fix32_t a,fix32_t b,fix32_t c); +m_int ASMAPI MGL_backfacing(fix32_t dx1,fix32_t dy1,fix32_t dx2,fix32_t dy2); +void ASMAPI MGL_memcpy(void *dst,void *src,m_int n); + +#endif + +/* The following are special memcpy routines that properly handler reading + * and writing to virtual linear buffer memory by forcing the proper + * alignment. Note that the copy is extended to use a DWORD copy of speed. + */ + +void ASMAPI MGL_memcpyVIRTSRC(void *dst,void *src,m_int n); +void ASMAPI MGL_memcpyVIRTDST(void *dst,void *src,m_int n); + +/* Function to find an MGL system file's full pathname */ + +bool MGLAPI _MGL_findFile(char *validpath,const char *dir, const char *filename, const char *mode); + +/* Override the internal MGL file I/O functions */ + +void MGLAPI MGL_setFileIO(fileio_t *fio); + +/* The following dummy symbols are used to link in driver files to be used. A + * driver is not active until it is linked in with the MGL_registerDriver + * call. Because we dont export globals in DLLs, we provide functions to + * get the address of the drivers. However for a static link library we + * need to use globals so that if the driver data is unreferenced, it will + * not be linked in with the code. + */ + +#ifndef BUILD_MGL +#if defined(MGL_DLL) && !defined(BUILD_MGLDLL) +void * MGLAPI VGA4_getDriverAddr(void); +void * MGLAPI VGAX_getDriverAddr(void); +void * MGLAPI SVGA4_getDriverAddr(void); +void * MGLAPI SVGA8_getDriverAddr(void); +void * MGLAPI SVGA16_getDriverAddr(void); +void * MGLAPI SVGA24_getDriverAddr(void); +void * MGLAPI SVGA32_getDriverAddr(void); +#if !defined(__16BIT__) +void * MGLAPI VGA8_getDriverAddr(void); +void * MGLAPI LINEAR8_getDriverAddr(void); +void * MGLAPI LINEAR16_getDriverAddr(void); +void * MGLAPI LINEAR24_getDriverAddr(void); +void * MGLAPI LINEAR32_getDriverAddr(void); +void * MGLAPI ACCEL8_getDriverAddr(void); +void * MGLAPI ACCEL16_getDriverAddr(void); +void * MGLAPI ACCEL24_getDriverAddr(void); +void * MGLAPI ACCEL32_getDriverAddr(void); +#if defined(MGLWIN) || defined(__WINDOWS__) +void * MGLAPI DDRAW8_getDriverAddr(void); +void * MGLAPI DDRAW16_getDriverAddr(void); +void * MGLAPI DDRAW24_getDriverAddr(void); +void * MGLAPI DDRAW32_getDriverAddr(void); +#endif +#endif +void * MGLAPI PACKED1_getDriverAddr(void); +void * MGLAPI PACKED4_getDriverAddr(void); +void * MGLAPI PACKED8_getDriverAddr(void); +void * MGLAPI PACKED16_getDriverAddr(void); +void * MGLAPI PACKED24_getDriverAddr(void); +void * MGLAPI PACKED32_getDriverAddr(void); +#define VGA4_driver VGA4_getDriverAddr() +#define VGAX_driver VGAX_getDriverAddr() +#define SVGA4_driver SVGA4_getDriverAddr() +#define SVGA8_driver SVGA8_getDriverAddr() +#define SVGA16_driver SVGA16_getDriverAddr() +#define SVGA24_driver SVGA24_getDriverAddr() +#define SVGA32_driver SVGA32_getDriverAddr() +#if !defined(__16BIT__) +#define VGA8_driver VGA8_getDriverAddr() +#define LINEAR8_driver LINEAR8_getDriverAddr() +#define LINEAR16_driver LINEAR16_getDriverAddr() +#define LINEAR24_driver LINEAR24_getDriverAddr() +#define LINEAR32_driver LINEAR32_getDriverAddr() +#define ACCEL8_driver ACCEL8_getDriverAddr() +#define ACCEL16_driver ACCEL16_getDriverAddr() +#define ACCEL24_driver ACCEL24_getDriverAddr() +#define ACCEL32_driver ACCEL32_getDriverAddr() +#if defined(MGLWIN) || defined(__WINDOWS__) +#define DDRAW8_driver DDRAW8_getDriverAddr() +#define DDRAW16_driver DDRAW16_getDriverAddr() +#define DDRAW24_driver DDRAW24_getDriverAddr() +#define DDRAW32_driver DDRAW32_getDriverAddr() +#endif +#endif +#define PACKED1_driver PACKED1_getDriverAddr() +#define PACKED4_driver PACKED4_getDriverAddr() +#define PACKED8_driver PACKED8_getDriverAddr() +#define PACKED16_driver PACKED16_getDriverAddr() +#define PACKED24_driver PACKED24_getDriverAddr() +#define PACKED32_driver PACKED32_getDriverAddr() +#else +extern m_int _VARAPI VGA4_driver[]; +extern m_int _VARAPI VGAX_driver[]; +extern m_int _VARAPI SVGA4_driver[]; +extern m_int _VARAPI SVGA8_driver[]; +extern m_int _VARAPI SVGA16_driver[]; +extern m_int _VARAPI SVGA24_driver[]; +extern m_int _VARAPI SVGA32_driver[]; +#if !defined(__16BIT__) +extern m_int _VARAPI VGA8_driver[]; +extern m_int _VARAPI LINEAR8_driver[]; +extern m_int _VARAPI LINEAR16_driver[]; +extern m_int _VARAPI LINEAR24_driver[]; +extern m_int _VARAPI LINEAR32_driver[]; +extern m_int _VARAPI ACCEL8_driver[]; +extern m_int _VARAPI ACCEL16_driver[]; +extern m_int _VARAPI ACCEL24_driver[]; +extern m_int _VARAPI ACCEL32_driver[]; +#if defined(MGLWIN) || defined(__WINDOWS__) +extern m_int _VARAPI DDRAW8_driver[]; +extern m_int _VARAPI DDRAW16_driver[]; +extern m_int _VARAPI DDRAW24_driver[]; +extern m_int _VARAPI DDRAW32_driver[]; +#endif +#endif +extern m_int _VARAPI PACKED1_driver[]; +extern m_int _VARAPI PACKED4_driver[]; +extern m_int _VARAPI PACKED8_driver[]; +extern m_int _VARAPI PACKED16_driver[]; +extern m_int _VARAPI PACKED24_driver[]; +extern m_int _VARAPI PACKED32_driver[]; +#endif +#endif + +/*--------------------------------------------------------------------------- + * Memory allocation and utility functions. + *-------------------------------------------------------------------------*/ + +#ifndef __16BIT__ +#define _HUGE +#else +#define _HUGE _huge +#endif + +void MGL_availableMemory(ulong *physical,ulong *total); +void MGL_useLocalMalloc(void _HUGE * (*malloc)(long size),void (*free)(void _HUGE *p)); +void * MGLAPI MGL_malloc(long size); +void * MGLAPI MGL_calloc(long size,long n); +void MGLAPI MGL_free(void _HUGE *p); +void MGLAPI MGL_memset(void _HUGE *s,m_int c,long n); +void MGLAPI MGL_memsetw(void _HUGE *s,m_int c,long n); +void MGLAPI MGL_memsetl(void _HUGE *s,long c,long n); + +/*--------------------------------------------------------------------------- + * Set a fullscreen suspend application callback function. This is used in + * fullscreen video modes to allow switching back to the normal operating + * system graphical shell (such as Windows GDI, OS/2 PM etc). + *-------------------------------------------------------------------------*/ + +typedef m_int (ASMAPI *MGL_suspend_cb_t)(MGLDC *dc,m_int flags); +void MGLAPI MGL_setSuspendAppCallback(MGL_suspend_cb_t staveState); + +/*--------------------------------------------------------------------------- + * Tell the MGL to use a pre-loaded ACCEL.DRV driver file. This allows + * you to link with the SciTech WinDirect/Pro and WinDirect/Ultra device + * support libraries and tell the MGL to use the device support drivers. + * If the user has a real ACCEL.DRV driver file in the standard location + * on their machine, this driver file will still be used. + *-------------------------------------------------------------------------*/ + +void MGLAPI MGL_setACCELDriver(void *driver); + +/*---------------------- Inline functions as Macros -----------------------*/ + +#define MGL_equalPoint(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y) + +#define MGL_equalRect(r1,r2) ((r1).left == (r2).left && \ + (r1).top == (r2).top && \ + (r1).right == (r2).right && \ + (r1).bottom == (r2).bottom) + +#define MGL_emptyRect(r) ((r).bottom <= (r).top || \ + (r).right <= (r).left) + +#define MGL_disjointRect(r1,r2) ((r1).right <= (r2).left || \ + (r1).left >= (r2).right || \ + (r1).bottom <= (r2).top || \ + (r1).top >= (r2).bottom) + +#define MGL_sectRect(s1,s2,d) \ + ((d)->left = MAX((s1).left,(s2).left), \ + (d)->right = MIN((s1).right,(s2).right), \ + (d)->top = MAX((s1).top,(s2).top), \ + (d)->bottom = MIN((s1).bottom,(s2).bottom), \ + !MGL_emptyRect(*d)) + +#define MGL_sectRectFast(s1,s2,d) \ + (d)->left = MAX((s1).left,(s2).left); \ + (d)->right = MIN((s1).right,(s2).right); \ + (d)->top = MAX((s1).top,(s2).top); \ + (d)->bottom = MIN((s1).bottom,(s2).bottom) + +#define MGL_sectRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ + ((d)->left = MAX(l1,l2), \ + (d)->right = MIN(r1,r2), \ + (d)->top = MAX(t1,t2), \ + (d)->bottom = MIN(b1,b2), \ + !MGL_emptyRect(*d)) + +#define MGL_sectRectFastCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ + (d)->left = MAX(l1,l2); \ + (d)->right = MIN(r1,r2); \ + (d)->top = MAX(t1,t2); \ + (d)->bottom = MIN(b1,b2) + +#define MGL_unionRect(s1,s2,d) \ + (d)->left = MIN((s1).left,(s2).left); \ + (d)->right = MAX((s1).right,(s2).right); \ + (d)->top = MIN((s1).top,(s2).top); \ + (d)->bottom = MAX((s1).bottom,(s2).bottom) + +#define MGL_unionRectCoord(l1,t1,r1,b1,l2,t2,r2,b2,d) \ + (d)->left = MIN(l1,l2); \ + (d)->right = MAX(r1,r2); \ + (d)->top = MIN(t1,t2); \ + (d)->bottom = MAX(b1,b2) + +#define MGL_offsetRect(r,dx,dy) \ + { (r).left += dx; (r).right += dx; \ + (r).top += dy; (r).bottom += dy; } + +#define MGL_insetRect(r,dx,dy) \ + { (r).left += dx; (r).right -= dx; \ + (r).top += dy; (r).bottom -= dy; \ + if (MGL_emptyRect(r)) \ + (r).left = (r).right = (r).top = (r).bottom = 0; } + +#define MGL_ptInRect(p,r) ((p).x >= (r).left && \ + (p).x < (r).right && \ + (p).y >= (r).top && \ + (p).y < (r).bottom) + +#define MGL_ptInRectCoord(x,y,r) ((x) >= (r).left && \ + (x) < (r).right && \ + (y) >= (r).top && \ + (y) < (r).bottom) + +#define MGL_ptInRegion(p,r) MGL_ptInRegionCoord((p).x,(p).y,r) + +#define MGL_pixel(p) MGL_pixelCoord((p).x,(p).y) +#define MGL_getPixel(p) MGL_getPixelCoord((p).x,(p).y) +#define MGL_pixelFast(p) MGL_pixelCoordFast((p).x,(p).y) +#define MGL_getPixelFast(p) MGL_getPixelCoordFast((p).x,(p).y) +#define MGL_moveTo(p) MGL_moveToCoord((p).x,(p).y) +#define MGL_moveRel(p) MGL_moveRelCoord((p).x,(p).y) +#define MGL_line(p1,p2) MGL_lineCoord((p1).x,(p1).y,(p2).x,(p2).y) +#define MGL_lineFast(p1,p2) MGL_lineCoordFast((p1).x,(p1).y,(p2).x,(p2).y) +#define MGL_lineFX(p1,p2) MGL_lineCoordFX((p1).x,(p1).y,(p2).x,(p2).y) +#define MGL_lineFastFX(p1,p2) MGL_lineCoordFastFX((p1).x,(p1).y,(p2).x,(p2).y) +#define MGL_cLineFast(p1,p2) MGL_cLineCoordFast((p1).p.x,(p1).p.y,(p1).c,(p2).p.x,(p2).p.y,(p2).c) +#define MGL_rgbLineFast(p1,p2) MGL_rgbLineCoordFast((p1).p.x,(p1).p.y,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).c.r,(p2).c.g,(p2).c.b) +#define MGL_zLineFast(p1,p2) MGL_zLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p2).p.x,(p2).p.y,(p2).z) +#define MGL_czLineFast(p1,p2) MGL_czLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c,(p2).p.x,(p2).p.y,(p2).z,(p2).c) +#define MGL_rgbzLineFast(p1,p2) MGL_rgbzLineCoordFast((p1).p.x,(p1).p.y,(p1).z,(p1).c.r,(p1).c.g,(p1).c.b,(p2).p.x,(p2).p.y,(p2).z,(p2).c.r,(p2).c.g,(p2).c.b) + +#define MGL_zClearPt(lt,rb,z) MGL_zClearCoord((lt).x,(lt).y, \ + (rb).x,(rb).y,z) +#define MGL_zClear(r,z) MGL_zClearCoord((r).left,(r).top, \ + (r).right,(r).bottom,z) +#define MGL_lineTo(p) MGL_lineToCoord((p).x,(p).y) +#define MGL_lineRel(p) MGL_lineRelCoord((p).x,(p).y); +#define MGL_rectPt(lt,rb) MGL_rectCoord((lt).x,(lt).y,(rb).x,(rb).y) +#define MGL_rect(r) MGL_rectCoord((r).left,(r).top, \ + (r).right,(r).bottom) +#define MGL_drawBorder(r,s,t) MGL_drawBorderCoord((r).left,(r).top, \ + (r).right,(r).bottom,(s),(t)) +#define MGL_fillRectPt(lt,rb) MGL_fillRectCoord((lt).x,(lt).y, \ + (rb).x,(rb).y) +#define MGL_fillRect(r) MGL_fillRectCoord((r).left,(r).top, \ + (r).right,(r).bottom) +#define MGL_bitBlt(d,s,r,dl,dt,op) MGL_bitBltCoord((d),(s),(r).left, \ + (r).top,(r).right,(r).bottom,dl,dt,op) +#define MGL_bitBltLin(d,s,so,r,op) MGL_bitBltLinCoord((d),(s),so, \ + (r).left,(r).top,(r).right,(r).bottom,op) +#define MGL_stretchBlt(d,s,sr,dr) MGL_stretchBltCoord((d),(s),(sr).left, \ + (sr).top,(sr).right,(sr).bottom, \ + (dr).left,(dr).top,(dr).right,(dr).bottom) +#define MGL_transBlt(d,s,r,dl,dt,c,st) MGL_transBltCoord((d),(s),(r).left, \ + (r).top,(r).right,(r).bottom,dl,dt,c,st) +#define MGL_transBltLin(d,s,so,r,c,st) MGL_transBltLinCoord((d),(s),so, \ + (r).left,(r).top,(r).right,(r).bottom,c,st) +#define MGL_getDivot(dc,r,divot) MGL_getDivotCoord(dc,(r).left,(r).top, \ + (r).right,(r).bottom,divot) +#define MGL_divotSize(dc,r) MGL_divotSizeCoord(dc,(r).left,(r).top,\ + (r).right,(r).bottom) +#define MGL_isSimpleRegion(r) (((region_t*)(r))->spans == NULL) +#define MGL_rgnLine(p1,p2,p) MGL_rgnLineCoord((p1).x,(p1).y,(p2).x,(p2).y,p) +#define MGL_rgnLineFX(p1,p2,p) MGL_rgnLineCoordFX((p1).x,(p1).y,(p2).x,(p2).y,p) +#define MGL_rgnSolidRectPt(lt,rb) MGL_rgnSolidRectCoord((lt).x,(lt).y, \ + (rb).x,(rb).y) +#define MGL_rgnSolidRect(r) MGL_rgnSolidRectCoord((r).left,(r).top, \ + (r).right,(r).bottom) + +/* Fast color packing/unpacking routines implemented as macros */ + +#define MGL_packColorFast(pf,R,G,B) \ + ((ulong)(((uchar)(R) >> (pf)->redAdjust) & (pf)->redMask) << (pf)->redPos) \ + | ((ulong)(((uchar)(G) >> (pf)->greenAdjust) & (pf)->greenMask) << (pf)->greenPos) \ + | ((ulong)(((uchar)(B) >> (pf)->blueAdjust) & (pf)->blueMask) << (pf)->bluePos) + +#define MGL_unpackColorFast(pf,c,R,G,B) \ +{ \ + (R) = (uchar)((((ulong)(c) >> (pf)->redPos) & (pf)->redMask) << (pf)->redAdjust); \ + (G) = (uchar)((((ulong)(c) >> (pf)->greenPos) & (pf)->greenMask) << (pf)->greenAdjust);\ + (B) = (uchar)((((ulong)(c) >> (pf)->bluePos) & (pf)->blueMask) << (pf)->blueAdjust); \ +} + +/* Macros to access the RGB components in a packed 24 bit RGB tuple */ + +#define MGL_rgbRed(c) (((uchar*)&(c))[2]) +#define MGL_rgbGreen(c) (((uchar*)&(c))[1]) +#define MGL_rgbBlue(c) (((uchar*)&(c))[0]) + +/* Fast 24 bit color packing/unpacking routines implemented as macros */ + +#define MGL_packColorRGBFast(R,G,B) \ + (((ulong)((uchar)(R)) << 16) | ((ulong)((uchar)(G)) << 8) | (uchar)(B)) + +#define MGL_packColorRGBFast2(c,R,G,B) \ +{ \ + MGL_rgbRed(c) = (uchar)(R); \ + MGL_rgbGreen(c) = (uchar)(G); \ + MGL_rgbBlue(c) = (uchar)(B); \ +} + +#define MGL_unpackColorRGBFast(c,R,G,B) \ +{ \ + (R) = MGL_rgbRed(c); \ + (G) = MGL_rgbGreen(c); \ + (B) = MGL_rgbBlue(c); \ +} + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ + +#include "mglrect.hpp" /* Include C++ point/rectangle classes */ + +#endif /* __cplusplus */ + +/* Include appropriate platform specific bindings */ + +#if defined(MGLWIN) || defined(__WINDOWS__) +#include "mglwin.h" +#elif defined(MGLPM) || defined(__OS2__) +/*#include "mglpm.h"*/ +#elif defined(MGLX) || defined(__UNIX__) +/*#include "mglx.h"*/ +#else +#include "mgldos.h" +#endif + +#pragma pack() /* Return to default packing */ + +#endif /* __MGRAPH_H */ diff --git a/WinQuake/screen.c b/WinQuake/screen.c index b39be67..dd425c3 100644 --- a/WinQuake/screen.c +++ b/WinQuake/screen.c @@ -1,991 +1,991 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// screen.c -- master for refresh, status bar, console, chat, notify, etc - -#include "quakedef.h" -#include "r_local.h" - -// only the refresh window will be updated unless these variables are flagged -int scr_copytop; -int scr_copyeverything; - -float scr_con_current; -float scr_conlines; // lines of console to display - -float oldscreensize, oldfov; -cvar_t scr_viewsize = {"viewsize","100", true}; -cvar_t scr_fov = {"fov","90"}; // 10 - 170 -cvar_t scr_conspeed = {"scr_conspeed","300"}; -cvar_t scr_centertime = {"scr_centertime","2"}; -cvar_t scr_showram = {"showram","1"}; -cvar_t scr_showturtle = {"showturtle","0"}; -cvar_t scr_showpause = {"showpause","1"}; -cvar_t scr_printspeed = {"scr_printspeed","8"}; - -qboolean scr_initialized; // ready to draw - -qpic_t *scr_ram; -qpic_t *scr_net; -qpic_t *scr_turtle; - -int scr_fullupdate; - -int clearconsole; -int clearnotify; - -viddef_t vid; // global video state - -vrect_t *pconupdate; -vrect_t scr_vrect; - -qboolean scr_disabled_for_loading; -qboolean scr_drawloading; -float scr_disabled_time; -qboolean scr_skipupdate; - -qboolean block_drawing; - -void SCR_ScreenShot_f (void); - -/* -=============================================================================== - -CENTER PRINTING - -=============================================================================== -*/ - -char scr_centerstring[1024]; -float scr_centertime_start; // for slow victory printing -float scr_centertime_off; -int scr_center_lines; -int scr_erase_lines; -int scr_erase_center; - -/* -============== -SCR_CenterPrint - -Called for important messages that should stay in the center of the screen -for a few moments -============== -*/ -void SCR_CenterPrint (char *str) -{ - strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); - scr_centertime_off = scr_centertime.value; - scr_centertime_start = cl.time; - -// count the number of lines for centering - scr_center_lines = 1; - while (*str) - { - if (*str == '\n') - scr_center_lines++; - str++; - } -} - -void SCR_EraseCenterString (void) -{ - int y; - - if (scr_erase_center++ > vid.numpages) - { - scr_erase_lines = 0; - return; - } - - if (scr_center_lines <= 4) - y = vid.height*0.35; - else - y = 48; - - scr_copytop = 1; - Draw_TileClear (0, y,vid.width, 8*scr_erase_lines); -} - -void SCR_DrawCenterString (void) -{ - char *start; - int l; - int j; - int x, y; - int remaining; - -// the finale prints the characters one at a time - if (cl.intermission) - remaining = scr_printspeed.value * (cl.time - scr_centertime_start); - else - remaining = 9999; - - scr_erase_center = 0; - start = scr_centerstring; - - if (scr_center_lines <= 4) - y = vid.height*0.35; - else - y = 48; - - do - { - // scan the width of the line - for (l=0 ; l<40 ; l++) - if (start[l] == '\n' || !start[l]) - break; - x = (vid.width - l*8)/2; - for (j=0 ; j scr_erase_lines) - scr_erase_lines = scr_center_lines; - - scr_centertime_off -= host_frametime; - - if (scr_centertime_off <= 0 && !cl.intermission) - return; - if (key_dest != key_game) - return; - - SCR_DrawCenterString (); -} - -//============================================================================= - -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) -{ - float a; - float x; - - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width/tan(fov_x/360*M_PI); - - a = atan (height/x); - - a = a*360/M_PI; - - return a; -} - -/* -================= -SCR_CalcRefdef - -Must be called whenever vid changes -Internal use only -================= -*/ -static void SCR_CalcRefdef (void) -{ - vrect_t vrect; - float size; - - scr_fullupdate = 0; // force a background redraw - vid.recalc_refdef = 0; - -// force the status bar to redraw - Sbar_Changed (); - -//======================================== - -// bound viewsize - if (scr_viewsize.value < 30) - Cvar_Set ("viewsize","30"); - if (scr_viewsize.value > 120) - Cvar_Set ("viewsize","120"); - -// bound field of view - if (scr_fov.value < 10) - Cvar_Set ("fov","10"); - if (scr_fov.value > 170) - Cvar_Set ("fov","170"); - - r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); - -// intermission is always full screen - if (cl.intermission) - size = 120; - else - size = scr_viewsize.value; - - if (size >= 120) - sb_lines = 0; // no status bar at all - else if (size >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - -// these calculations mirror those in R_Init() for r_refdef, but take no -// account of water warping - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_SetVrect (&vrect, &scr_vrect, sb_lines); - -// guard against going from one mode to another that's less than half the -// vertical resolution - if (scr_con_current > vid.height) - scr_con_current = vid.height; - -// notify the refresh of the change - R_ViewChanged (&vrect, sb_lines, vid.aspect); -} - - -/* -================= -SCR_SizeUp_f - -Keybinding command -================= -*/ -void SCR_SizeUp_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value+10); - vid.recalc_refdef = 1; -} - - -/* -================= -SCR_SizeDown_f - -Keybinding command -================= -*/ -void SCR_SizeDown_f (void) -{ - Cvar_SetValue ("viewsize",scr_viewsize.value-10); - vid.recalc_refdef = 1; -} - -//============================================================================ - -/* -================== -SCR_Init -================== -*/ -void SCR_Init (void) -{ - Cvar_RegisterVariable (&scr_fov); - Cvar_RegisterVariable (&scr_viewsize); - Cvar_RegisterVariable (&scr_conspeed); - Cvar_RegisterVariable (&scr_showram); - Cvar_RegisterVariable (&scr_showturtle); - Cvar_RegisterVariable (&scr_showpause); - Cvar_RegisterVariable (&scr_centertime); - Cvar_RegisterVariable (&scr_printspeed); - -// -// register our commands -// - Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddCommand ("sizeup",SCR_SizeUp_f); - Cmd_AddCommand ("sizedown",SCR_SizeDown_f); - - scr_ram = Draw_PicFromWad ("ram"); - scr_net = Draw_PicFromWad ("net"); - scr_turtle = Draw_PicFromWad ("turtle"); - - scr_initialized = true; -} - - - -/* -============== -SCR_DrawRam -============== -*/ -void SCR_DrawRam (void) -{ - if (!scr_showram.value) - return; - - if (!r_cache_thrash) - return; - - Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); -} - -/* -============== -SCR_DrawTurtle -============== -*/ -void SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle.value) - return; - - if (host_frametime < 0.1) - { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); -} - -/* -============== -SCR_DrawNet -============== -*/ -void SCR_DrawNet (void) -{ - if (realtime - cl.last_received_message < 0.3) - return; - if (cls.demoplayback) - return; - - Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); -} - -/* -============== -DrawPause -============== -*/ -void SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause.value) // turn off for screenshots - return; - - if (!cl.paused) - return; - - pic = Draw_CachePic ("gfx/pause.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); -} - - - -/* -============== -SCR_DrawLoading -============== -*/ -void SCR_DrawLoading (void) -{ - qpic_t *pic; - - if (!scr_drawloading) - return; - - pic = Draw_CachePic ("gfx/loading.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); -} - - - -//============================================================================= - - -/* -================== -SCR_SetUpToDrawConsole -================== -*/ -void SCR_SetUpToDrawConsole (void) -{ - Con_CheckResize (); - - if (scr_drawloading) - return; // never a console with loading plaque - -// decide on the height of the console - con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; - - if (con_forcedup) - { - scr_conlines = vid.height; // full screen - scr_con_current = scr_conlines; - } - else if (key_dest == key_console) - scr_conlines = vid.height/2; // half screen - else - scr_conlines = 0; // none visible - - if (scr_conlines < scr_con_current) - { - scr_con_current -= scr_conspeed.value*host_frametime; - if (scr_conlines > scr_con_current) - scr_con_current = scr_conlines; - - } - else if (scr_conlines > scr_con_current) - { - scr_con_current += scr_conspeed.value*host_frametime; - if (scr_conlines < scr_con_current) - scr_con_current = scr_conlines; - } - - if (clearconsole++ < vid.numpages) - { - scr_copytop = 1; - Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); - Sbar_Changed (); - } - else if (clearnotify++ < vid.numpages) - { - scr_copytop = 1; - Draw_TileClear (0,0,vid.width, con_notifylines); - } - else - con_notifylines = 0; -} - -/* -================== -SCR_DrawConsole -================== -*/ -void SCR_DrawConsole (void) -{ - if (scr_con_current) - { - scr_copyeverything = 1; - Con_DrawConsole (scr_con_current, true); - clearconsole = 0; - } - else - { - if (key_dest == key_game || key_dest == key_message) - Con_DrawNotify (); // only draw notify in game - } -} - - -/* -============================================================================== - - SCREEN SHOTS - -============================================================================== -*/ - - -typedef struct -{ - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - unsigned short xmin,ymin,xmax,ymax; - unsigned short hres,vres; - unsigned char palette[48]; - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - char filler[58]; - unsigned char data; // unbounded -} pcx_t; - -/* -============== -WritePCXfile -============== -*/ -void WritePCXfile (char *filename, byte *data, int width, int height, - int rowbytes, byte *palette) -{ - int i, j, length; - pcx_t *pcx; - byte *pack; - - pcx = Hunk_TempAlloc (width*height*2+1000); - if (pcx == NULL) - { - Con_Printf("SCR_ScreenShot_f: not enough memory\n"); - return; - } - - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = LittleShort((short)(width-1)); - pcx->ymax = LittleShort((short)(height-1)); - pcx->hres = LittleShort((short)width); - pcx->vres = LittleShort((short)height); - Q_memset (pcx->palette,0,sizeof(pcx->palette)); - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = LittleShort((short)width); - pcx->palette_type = LittleShort(2); // not a grey scale - Q_memset (pcx->filler,0,sizeof(pcx->filler)); - -// pack the image - pack = &pcx->data; - - for (i=0 ; i 60) - { - scr_disabled_for_loading = false; - Con_Printf ("load failed.\n"); - } - else - return; - } - - if (cls.state == ca_dedicated) - return; // stdout only - - if (!scr_initialized || !con_initialized) - return; // not initialized yet - - if (scr_viewsize.value != oldscr_viewsize) - { - oldscr_viewsize = scr_viewsize.value; - vid.recalc_refdef = 1; - } - -// -// check for vid changes -// - if (oldfov != scr_fov.value) - { - oldfov = scr_fov.value; - vid.recalc_refdef = true; - } - - if (oldlcd_x != lcd_x.value) - { - oldlcd_x = lcd_x.value; - vid.recalc_refdef = true; - } - - if (oldscreensize != scr_viewsize.value) - { - oldscreensize = scr_viewsize.value; - vid.recalc_refdef = true; - } - - if (vid.recalc_refdef) - { - // something changed, so reorder the screen - SCR_CalcRefdef (); - } - -// -// do 3D refresh drawing, and then update the screen -// - D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly - - if (scr_fullupdate++ < vid.numpages) - { // clear the entire screen - scr_copyeverything = 1; - Draw_TileClear (0,0,vid.width,vid.height); - Sbar_Changed (); - } - - pconupdate = NULL; - - - SCR_SetUpToDrawConsole (); - SCR_EraseCenterString (); - - D_DisableBackBufferAccess (); // for adapters that can't stay mapped in - // for linear writes all the time - - VID_LockBuffer (); - - V_RenderView (); - - VID_UnlockBuffer (); - - D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly - - if (scr_drawdialog) - { - Sbar_Draw (); - Draw_FadeScreen (); - SCR_DrawNotifyString (); - scr_copyeverything = true; - } - else if (scr_drawloading) - { - SCR_DrawLoading (); - Sbar_Draw (); - } - else if (cl.intermission == 1 && key_dest == key_game) - { - Sbar_IntermissionOverlay (); - } - else if (cl.intermission == 2 && key_dest == key_game) - { - Sbar_FinaleOverlay (); - SCR_CheckDrawCenterString (); - } - else if (cl.intermission == 3 && key_dest == key_game) - { - SCR_CheckDrawCenterString (); - } - else - { - SCR_DrawRam (); - SCR_DrawNet (); - SCR_DrawTurtle (); - SCR_DrawPause (); - SCR_CheckDrawCenterString (); - Sbar_Draw (); - SCR_DrawConsole (); - M_Draw (); - } - - D_DisableBackBufferAccess (); // for adapters that can't stay mapped in - // for linear writes all the time - if (pconupdate) - { - D_UpdateRects (pconupdate); - } - - V_UpdatePalette (); - -// -// update one of three areas -// - - if (scr_copyeverything) - { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.pnext = 0; - - VID_Update (&vrect); - } - else if (scr_copytop) - { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - sb_lines; - vrect.pnext = 0; - - VID_Update (&vrect); - } - else - { - vrect.x = scr_vrect.x; - vrect.y = scr_vrect.y; - vrect.width = scr_vrect.width; - vrect.height = scr_vrect.height; - vrect.pnext = 0; - - VID_Update (&vrect); - } -} - - -/* -================== -SCR_UpdateWholeScreen -================== -*/ -void SCR_UpdateWholeScreen (void) -{ - scr_fullupdate = 0; - SCR_UpdateScreen (); -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// screen.c -- master for refresh, status bar, console, chat, notify, etc + +#include "quakedef.h" +#include "r_local.h" + +// only the refresh window will be updated unless these variables are flagged +int scr_copytop; +int scr_copyeverything; + +float scr_con_current; +float scr_conlines; // lines of console to display + +float oldscreensize, oldfov; +cvar_t scr_viewsize = {"viewsize","100", true}; +cvar_t scr_fov = {"fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {"scr_conspeed","300"}; +cvar_t scr_centertime = {"scr_centertime","2"}; +cvar_t scr_showram = {"showram","1"}; +cvar_t scr_showturtle = {"showturtle","0"}; +cvar_t scr_showpause = {"showpause","1"}; +cvar_t scr_printspeed = {"scr_printspeed","8"}; + +qboolean scr_initialized; // ready to draw + +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; + +int scr_fullupdate; + +int clearconsole; +int clearnotify; + +viddef_t vid; // global video state + +vrect_t *pconupdate; +vrect_t scr_vrect; + +qboolean scr_disabled_for_loading; +qboolean scr_drawloading; +float scr_disabled_time; +qboolean scr_skipupdate; + +qboolean block_drawing; + +void SCR_ScreenShot_f (void); + +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + +void SCR_EraseCenterString (void) +{ + int y; + + if (scr_erase_center++ > vid.numpages) + { + scr_erase_lines = 0; + return; + } + + if (scr_center_lines <= 4) + y = vid.height*0.35; + else + y = 48; + + scr_copytop = 1; + Draw_TileClear (0, y,vid.width, 8*scr_erase_lines); +} + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int j; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.height*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l*8)/2; + for (j=0 ; j scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +//============================================================================= + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width/tan(fov_x/360*M_PI); + + a = atan (height/x); + + a = a*360/M_PI; + + return a; +} + +/* +================= +SCR_CalcRefdef + +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + vrect_t vrect; + float size; + + scr_fullupdate = 0; // force a background redraw + vid.recalc_refdef = 0; + +// force the status bar to redraw + Sbar_Changed (); + +//======================================== + +// bound viewsize + if (scr_viewsize.value < 30) + Cvar_Set ("viewsize","30"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + +// bound field of view + if (scr_fov.value < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + + r_refdef.fov_x = scr_fov.value; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + +// intermission is always full screen + if (cl.intermission) + size = 120; + else + size = scr_viewsize.value; + + if (size >= 120) + sb_lines = 0; // no status bar at all + else if (size >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + +// these calculations mirror those in R_Init() for r_refdef, but take no +// account of water warping + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_SetVrect (&vrect, &scr_vrect, sb_lines); + +// guard against going from one mode to another that's less than half the +// vertical resolution + if (scr_con_current > vid.height) + scr_con_current = vid.height; + +// notify the refresh of the change + R_ViewChanged (&vrect, sb_lines, vid.aspect); +} + + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value+10); + vid.recalc_refdef = 1; +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); + vid.recalc_refdef = 1; +} + +//============================================================================ + +/* +================== +SCR_Init +================== +*/ +void SCR_Init (void) +{ + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + +// +// register our commands +// + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + scr_ram = Draw_PicFromWad ("ram"); + scr_net = Draw_PicFromWad ("net"); + scr_turtle = Draw_PicFromWad ("turtle"); + + scr_initialized = true; +} + + + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ + if (!scr_showram.value) + return; + + if (!r_cache_thrash) + return; + + Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle.value) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (realtime - cl.last_received_message < 0.3) + return; + if (cls.demoplayback) + return; + + Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); +} + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + qpic_t *pic; + + if (!scr_showpause.value) // turn off for screenshots + return; + + if (!cl.paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp"); + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); +} + + + +/* +============== +SCR_DrawLoading +============== +*/ +void SCR_DrawLoading (void) +{ + qpic_t *pic; + + if (!scr_drawloading) + return; + + pic = Draw_CachePic ("gfx/loading.lmp"); + Draw_Pic ( (vid.width - pic->width)/2, + (vid.height - 48 - pic->height)/2, pic); +} + + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + + if (scr_drawloading) + return; // never a console with loading plaque + +// decide on the height of the console + con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; + + if (con_forcedup) + { + scr_conlines = vid.height; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.height/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_frametime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_frametime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } + + if (clearconsole++ < vid.numpages) + { + scr_copytop = 1; + Draw_TileClear (0,(int)scr_con_current,vid.width, vid.height - (int)scr_con_current); + Sbar_Changed (); + } + else if (clearnotify++ < vid.numpages) + { + scr_copytop = 1; + Draw_TileClear (0,0,vid.width, con_notifylines); + } + else + con_notifylines = 0; +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + scr_copyeverything = 1; + Con_DrawConsole (scr_con_current, true); + clearconsole = 0; + } + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + + +typedef struct +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + unsigned short xmin,ymin,xmax,ymax; + unsigned short hres,vres; + unsigned char palette[48]; + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + char filler[58]; + unsigned char data; // unbounded +} pcx_t; + +/* +============== +WritePCXfile +============== +*/ +void WritePCXfile (char *filename, byte *data, int width, int height, + int rowbytes, byte *palette) +{ + int i, j, length; + pcx_t *pcx; + byte *pack; + + pcx = Hunk_TempAlloc (width*height*2+1000); + if (pcx == NULL) + { + Con_Printf("SCR_ScreenShot_f: not enough memory\n"); + return; + } + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = LittleShort((short)(width-1)); + pcx->ymax = LittleShort((short)(height-1)); + pcx->hres = LittleShort((short)width); + pcx->vres = LittleShort((short)height); + Q_memset (pcx->palette,0,sizeof(pcx->palette)); + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = LittleShort((short)width); + pcx->palette_type = LittleShort(2); // not a grey scale + Q_memset (pcx->filler,0,sizeof(pcx->filler)); + +// pack the image + pack = &pcx->data; + + for (i=0 ; i 60) + { + scr_disabled_for_loading = false; + Con_Printf ("load failed.\n"); + } + else + return; + } + + if (cls.state == ca_dedicated) + return; // stdout only + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + if (scr_viewsize.value != oldscr_viewsize) + { + oldscr_viewsize = scr_viewsize.value; + vid.recalc_refdef = 1; + } + +// +// check for vid changes +// + if (oldfov != scr_fov.value) + { + oldfov = scr_fov.value; + vid.recalc_refdef = true; + } + + if (oldlcd_x != lcd_x.value) + { + oldlcd_x = lcd_x.value; + vid.recalc_refdef = true; + } + + if (oldscreensize != scr_viewsize.value) + { + oldscreensize = scr_viewsize.value; + vid.recalc_refdef = true; + } + + if (vid.recalc_refdef) + { + // something changed, so reorder the screen + SCR_CalcRefdef (); + } + +// +// do 3D refresh drawing, and then update the screen +// + D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly + + if (scr_fullupdate++ < vid.numpages) + { // clear the entire screen + scr_copyeverything = 1; + Draw_TileClear (0,0,vid.width,vid.height); + Sbar_Changed (); + } + + pconupdate = NULL; + + + SCR_SetUpToDrawConsole (); + SCR_EraseCenterString (); + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped in + // for linear writes all the time + + VID_LockBuffer (); + + V_RenderView (); + + VID_UnlockBuffer (); + + D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly + + if (scr_drawdialog) + { + Sbar_Draw (); + Draw_FadeScreen (); + SCR_DrawNotifyString (); + scr_copyeverything = true; + } + else if (scr_drawloading) + { + SCR_DrawLoading (); + Sbar_Draw (); + } + else if (cl.intermission == 1 && key_dest == key_game) + { + Sbar_IntermissionOverlay (); + } + else if (cl.intermission == 2 && key_dest == key_game) + { + Sbar_FinaleOverlay (); + SCR_CheckDrawCenterString (); + } + else if (cl.intermission == 3 && key_dest == key_game) + { + SCR_CheckDrawCenterString (); + } + else + { + SCR_DrawRam (); + SCR_DrawNet (); + SCR_DrawTurtle (); + SCR_DrawPause (); + SCR_CheckDrawCenterString (); + Sbar_Draw (); + SCR_DrawConsole (); + M_Draw (); + } + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped in + // for linear writes all the time + if (pconupdate) + { + D_UpdateRects (pconupdate); + } + + V_UpdatePalette (); + +// +// update one of three areas +// + + if (scr_copyeverything) + { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.pnext = 0; + + VID_Update (&vrect); + } + else if (scr_copytop) + { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - sb_lines; + vrect.pnext = 0; + + VID_Update (&vrect); + } + else + { + vrect.x = scr_vrect.x; + vrect.y = scr_vrect.y; + vrect.width = scr_vrect.width; + vrect.height = scr_vrect.height; + vrect.pnext = 0; + + VID_Update (&vrect); + } +} + + +/* +================== +SCR_UpdateWholeScreen +================== +*/ +void SCR_UpdateWholeScreen (void) +{ + scr_fullupdate = 0; + SCR_UpdateScreen (); +} diff --git a/WinQuake/screen.h b/WinQuake/screen.h index 845ab55..154f3e0 100644 --- a/WinQuake/screen.h +++ b/WinQuake/screen.h @@ -1,57 +1,57 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// screen.h - -void SCR_Init (void); - -void SCR_UpdateScreen (void); - - -void SCR_SizeUp (void); -void SCR_SizeDown (void); -void SCR_BringDownConsole (void); -void SCR_CenterPrint (char *str); - -void SCR_BeginLoadingPlaque (void); -void SCR_EndLoadingPlaque (void); - -int SCR_ModalMessage (char *text); - -extern float scr_con_current; -extern float scr_conlines; // lines of console to display - -extern int scr_fullupdate; // set to 0 to force full redraw -extern int sb_lines; - -extern int clearnotify; // set to 0 whenever notify text is drawn -extern qboolean scr_disabled_for_loading; -extern qboolean scr_skipupdate; - -extern cvar_t scr_viewsize; - -extern cvar_t scr_viewsize; - -// only the refresh window will be updated unless these variables are flagged -extern int scr_copytop; -extern int scr_copyeverything; - -extern qboolean block_drawing; - -void SCR_UpdateWholeScreen (void); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// screen.h + +void SCR_Init (void); + +void SCR_UpdateScreen (void); + + +void SCR_SizeUp (void); +void SCR_SizeDown (void); +void SCR_BringDownConsole (void); +void SCR_CenterPrint (char *str); + +void SCR_BeginLoadingPlaque (void); +void SCR_EndLoadingPlaque (void); + +int SCR_ModalMessage (char *text); + +extern float scr_con_current; +extern float scr_conlines; // lines of console to display + +extern int scr_fullupdate; // set to 0 to force full redraw +extern int sb_lines; + +extern int clearnotify; // set to 0 whenever notify text is drawn +extern qboolean scr_disabled_for_loading; +extern qboolean scr_skipupdate; + +extern cvar_t scr_viewsize; + +extern cvar_t scr_viewsize; + +// only the refresh window will be updated unless these variables are flagged +extern int scr_copytop; +extern int scr_copyeverything; + +extern qboolean block_drawing; + +void SCR_UpdateWholeScreen (void); diff --git a/WinQuake/server.h b/WinQuake/server.h index 2d4dfeb..e63c99e 100644 --- a/WinQuake/server.h +++ b/WinQuake/server.h @@ -1,257 +1,257 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// server.h - -typedef struct -{ - int maxclients; - int maxclientslimit; - struct client_s *clients; // [maxclients] - int serverflags; // episode completion information - qboolean changelevel_issued; // cleared when at SV_SpawnServer -} server_static_t; - -//============================================================================= - -typedef enum {ss_loading, ss_active} server_state_t; - -typedef struct -{ - qboolean active; // false if only a net client - - qboolean paused; - qboolean loadgame; // handle connections specially - - double time; - - int lastcheck; // used by PF_checkclient - double lastchecktime; - - char name[64]; // map name -#ifdef QUAKE2 - char startspot[64]; -#endif - char modelname[64]; // maps/.bsp, for model_precache[0] - struct model_s *worldmodel; - char *model_precache[MAX_MODELS]; // NULL terminated - struct model_s *models[MAX_MODELS]; - char *sound_precache[MAX_SOUNDS]; // NULL terminated - char *lightstyles[MAX_LIGHTSTYLES]; - int num_edicts; - int max_edicts; - edict_t *edicts; // can NOT be array indexed, because - // edict_t is variable sized, but can - // be used to reference the world ent - server_state_t state; // some actions are only valid during load - - sizebuf_t datagram; - byte datagram_buf[MAX_DATAGRAM]; - - sizebuf_t reliable_datagram; // copied to all clients at end of frame - byte reliable_datagram_buf[MAX_DATAGRAM]; - - sizebuf_t signon; - byte signon_buf[8192]; -} server_t; - - -#define NUM_PING_TIMES 16 -#define NUM_SPAWN_PARMS 16 - -typedef struct client_s -{ - qboolean active; // false = client is free - qboolean spawned; // false = don't send datagrams - qboolean dropasap; // has been told to go to another level - qboolean privileged; // can execute any host command - qboolean sendsignon; // only valid before spawned - - double last_message; // reliable messages must be sent - // periodically - - struct qsocket_s *netconnection; // communications handle - - usercmd_t cmd; // movement - vec3_t wishdir; // intended motion calced from cmd - - sizebuf_t message; // can be added to at any time, - // copied and clear once per frame - byte msgbuf[MAX_MSGLEN]; - edict_t *edict; // EDICT_NUM(clientnum+1) - char name[32]; // for printing to other people - int colors; - - float ping_times[NUM_PING_TIMES]; - int num_pings; // ping_times[num_pings%NUM_PING_TIMES] - -// spawn parms are carried from level to level - float spawn_parms[NUM_SPAWN_PARMS]; - -// client known data for deltas - int old_frags; -} client_t; - - -//============================================================================= - -// edict->movetype values -#define MOVETYPE_NONE 0 // never moves -#define MOVETYPE_ANGLENOCLIP 1 -#define MOVETYPE_ANGLECLIP 2 -#define MOVETYPE_WALK 3 // gravity -#define MOVETYPE_STEP 4 // gravity, special edge handling -#define MOVETYPE_FLY 5 -#define MOVETYPE_TOSS 6 // gravity -#define MOVETYPE_PUSH 7 // no clip to world, push and crush -#define MOVETYPE_NOCLIP 8 -#define MOVETYPE_FLYMISSILE 9 // extra size to monsters -#define MOVETYPE_BOUNCE 10 -#ifdef QUAKE2 -#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity -#define MOVETYPE_FOLLOW 12 // track movement of aiment -#endif - -// edict->solid values -#define SOLID_NOT 0 // no interaction with other objects -#define SOLID_TRIGGER 1 // touch on edge, but not blocking -#define SOLID_BBOX 2 // touch on edge, block -#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground -#define SOLID_BSP 4 // bsp clip, touch on edge, block - -// edict->deadflag values -#define DEAD_NO 0 -#define DEAD_DYING 1 -#define DEAD_DEAD 2 - -#define DAMAGE_NO 0 -#define DAMAGE_YES 1 -#define DAMAGE_AIM 2 - -// edict->flags -#define FL_FLY 1 -#define FL_SWIM 2 -//#define FL_GLIMPSE 4 -#define FL_CONVEYOR 4 -#define FL_CLIENT 8 -#define FL_INWATER 16 -#define FL_MONSTER 32 -#define FL_GODMODE 64 -#define FL_NOTARGET 128 -#define FL_ITEM 256 -#define FL_ONGROUND 512 -#define FL_PARTIALGROUND 1024 // not all corners are valid -#define FL_WATERJUMP 2048 // player jumping out of water -#define FL_JUMPRELEASED 4096 // for jump debouncing -#ifdef QUAKE2 -#define FL_FLASHLIGHT 8192 -#define FL_ARCHIVE_OVERRIDE 1048576 -#endif - -// entity effects - -#define EF_BRIGHTFIELD 1 -#define EF_MUZZLEFLASH 2 -#define EF_BRIGHTLIGHT 4 -#define EF_DIMLIGHT 8 -#ifdef QUAKE2 -#define EF_DARKLIGHT 16 -#define EF_DARKFIELD 32 -#define EF_LIGHT 64 -#define EF_NODRAW 128 -#endif - -#define SPAWNFLAG_NOT_EASY 256 -#define SPAWNFLAG_NOT_MEDIUM 512 -#define SPAWNFLAG_NOT_HARD 1024 -#define SPAWNFLAG_NOT_DEATHMATCH 2048 - -#ifdef QUAKE2 -// server flags -#define SFL_EPISODE_1 1 -#define SFL_EPISODE_2 2 -#define SFL_EPISODE_3 4 -#define SFL_EPISODE_4 8 -#define SFL_NEW_UNIT 16 -#define SFL_NEW_EPISODE 32 -#define SFL_CROSS_TRIGGERS 65280 -#endif - -//============================================================================ - -extern cvar_t teamplay; -extern cvar_t skill; -extern cvar_t deathmatch; -extern cvar_t coop; -extern cvar_t fraglimit; -extern cvar_t timelimit; - -extern server_static_t svs; // persistant server info -extern server_t sv; // local server - -extern client_t *host_client; - -extern jmp_buf host_abortserver; - -extern double host_time; - -extern edict_t *sv_player; - -//=========================================================== - -void SV_Init (void); - -void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count); -void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, - float attenuation); - -void SV_DropClient (qboolean crash); - -void SV_SendClientMessages (void); -void SV_ClearDatagram (void); - -int SV_ModelIndex (char *name); - -void SV_SetIdealPitch (void); - -void SV_AddUpdates (void); - -void SV_ClientThink (void); -void SV_AddClientToServer (struct qsocket_s *ret); - -void SV_ClientPrintf (char *fmt, ...); -void SV_BroadcastPrintf (char *fmt, ...); - -void SV_Physics (void); - -qboolean SV_CheckBottom (edict_t *ent); -qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink); - -void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); - -void SV_MoveToGoal (void); - -void SV_CheckForNewClients (void); -void SV_RunClients (void); -void SV_SaveSpawnparms (); -#ifdef QUAKE2 -void SV_SpawnServer (char *server, char *startspot); -#else -void SV_SpawnServer (char *server); -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// server.h + +typedef struct +{ + int maxclients; + int maxclientslimit; + struct client_s *clients; // [maxclients] + int serverflags; // episode completion information + qboolean changelevel_issued; // cleared when at SV_SpawnServer +} server_static_t; + +//============================================================================= + +typedef enum {ss_loading, ss_active} server_state_t; + +typedef struct +{ + qboolean active; // false if only a net client + + qboolean paused; + qboolean loadgame; // handle connections specially + + double time; + + int lastcheck; // used by PF_checkclient + double lastchecktime; + + char name[64]; // map name +#ifdef QUAKE2 + char startspot[64]; +#endif + char modelname[64]; // maps/.bsp, for model_precache[0] + struct model_s *worldmodel; + char *model_precache[MAX_MODELS]; // NULL terminated + struct model_s *models[MAX_MODELS]; + char *sound_precache[MAX_SOUNDS]; // NULL terminated + char *lightstyles[MAX_LIGHTSTYLES]; + int num_edicts; + int max_edicts; + edict_t *edicts; // can NOT be array indexed, because + // edict_t is variable sized, but can + // be used to reference the world ent + server_state_t state; // some actions are only valid during load + + sizebuf_t datagram; + byte datagram_buf[MAX_DATAGRAM]; + + sizebuf_t reliable_datagram; // copied to all clients at end of frame + byte reliable_datagram_buf[MAX_DATAGRAM]; + + sizebuf_t signon; + byte signon_buf[8192]; +} server_t; + + +#define NUM_PING_TIMES 16 +#define NUM_SPAWN_PARMS 16 + +typedef struct client_s +{ + qboolean active; // false = client is free + qboolean spawned; // false = don't send datagrams + qboolean dropasap; // has been told to go to another level + qboolean privileged; // can execute any host command + qboolean sendsignon; // only valid before spawned + + double last_message; // reliable messages must be sent + // periodically + + struct qsocket_s *netconnection; // communications handle + + usercmd_t cmd; // movement + vec3_t wishdir; // intended motion calced from cmd + + sizebuf_t message; // can be added to at any time, + // copied and clear once per frame + byte msgbuf[MAX_MSGLEN]; + edict_t *edict; // EDICT_NUM(clientnum+1) + char name[32]; // for printing to other people + int colors; + + float ping_times[NUM_PING_TIMES]; + int num_pings; // ping_times[num_pings%NUM_PING_TIMES] + +// spawn parms are carried from level to level + float spawn_parms[NUM_SPAWN_PARMS]; + +// client known data for deltas + int old_frags; +} client_t; + + +//============================================================================= + +// edict->movetype values +#define MOVETYPE_NONE 0 // never moves +#define MOVETYPE_ANGLENOCLIP 1 +#define MOVETYPE_ANGLECLIP 2 +#define MOVETYPE_WALK 3 // gravity +#define MOVETYPE_STEP 4 // gravity, special edge handling +#define MOVETYPE_FLY 5 +#define MOVETYPE_TOSS 6 // gravity +#define MOVETYPE_PUSH 7 // no clip to world, push and crush +#define MOVETYPE_NOCLIP 8 +#define MOVETYPE_FLYMISSILE 9 // extra size to monsters +#define MOVETYPE_BOUNCE 10 +#ifdef QUAKE2 +#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity +#define MOVETYPE_FOLLOW 12 // track movement of aiment +#endif + +// edict->solid values +#define SOLID_NOT 0 // no interaction with other objects +#define SOLID_TRIGGER 1 // touch on edge, but not blocking +#define SOLID_BBOX 2 // touch on edge, block +#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground +#define SOLID_BSP 4 // bsp clip, touch on edge, block + +// edict->deadflag values +#define DEAD_NO 0 +#define DEAD_DYING 1 +#define DEAD_DEAD 2 + +#define DAMAGE_NO 0 +#define DAMAGE_YES 1 +#define DAMAGE_AIM 2 + +// edict->flags +#define FL_FLY 1 +#define FL_SWIM 2 +//#define FL_GLIMPSE 4 +#define FL_CONVEYOR 4 +#define FL_CLIENT 8 +#define FL_INWATER 16 +#define FL_MONSTER 32 +#define FL_GODMODE 64 +#define FL_NOTARGET 128 +#define FL_ITEM 256 +#define FL_ONGROUND 512 +#define FL_PARTIALGROUND 1024 // not all corners are valid +#define FL_WATERJUMP 2048 // player jumping out of water +#define FL_JUMPRELEASED 4096 // for jump debouncing +#ifdef QUAKE2 +#define FL_FLASHLIGHT 8192 +#define FL_ARCHIVE_OVERRIDE 1048576 +#endif + +// entity effects + +#define EF_BRIGHTFIELD 1 +#define EF_MUZZLEFLASH 2 +#define EF_BRIGHTLIGHT 4 +#define EF_DIMLIGHT 8 +#ifdef QUAKE2 +#define EF_DARKLIGHT 16 +#define EF_DARKFIELD 32 +#define EF_LIGHT 64 +#define EF_NODRAW 128 +#endif + +#define SPAWNFLAG_NOT_EASY 256 +#define SPAWNFLAG_NOT_MEDIUM 512 +#define SPAWNFLAG_NOT_HARD 1024 +#define SPAWNFLAG_NOT_DEATHMATCH 2048 + +#ifdef QUAKE2 +// server flags +#define SFL_EPISODE_1 1 +#define SFL_EPISODE_2 2 +#define SFL_EPISODE_3 4 +#define SFL_EPISODE_4 8 +#define SFL_NEW_UNIT 16 +#define SFL_NEW_EPISODE 32 +#define SFL_CROSS_TRIGGERS 65280 +#endif + +//============================================================================ + +extern cvar_t teamplay; +extern cvar_t skill; +extern cvar_t deathmatch; +extern cvar_t coop; +extern cvar_t fraglimit; +extern cvar_t timelimit; + +extern server_static_t svs; // persistant server info +extern server_t sv; // local server + +extern client_t *host_client; + +extern jmp_buf host_abortserver; + +extern double host_time; + +extern edict_t *sv_player; + +//=========================================================== + +void SV_Init (void); + +void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count); +void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, + float attenuation); + +void SV_DropClient (qboolean crash); + +void SV_SendClientMessages (void); +void SV_ClearDatagram (void); + +int SV_ModelIndex (char *name); + +void SV_SetIdealPitch (void); + +void SV_AddUpdates (void); + +void SV_ClientThink (void); +void SV_AddClientToServer (struct qsocket_s *ret); + +void SV_ClientPrintf (char *fmt, ...); +void SV_BroadcastPrintf (char *fmt, ...); + +void SV_Physics (void); + +qboolean SV_CheckBottom (edict_t *ent); +qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink); + +void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); + +void SV_MoveToGoal (void); + +void SV_CheckForNewClients (void); +void SV_RunClients (void); +void SV_SaveSpawnparms (); +#ifdef QUAKE2 +void SV_SpawnServer (char *server, char *startspot); +#else +void SV_SpawnServer (char *server); +#endif diff --git a/WinQuake/snd_dma.c b/WinQuake/snd_dma.c index 4240a12..accb617 100644 --- a/WinQuake/snd_dma.c +++ b/WinQuake/snd_dma.c @@ -1,1017 +1,1017 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// snd_dma.c -- main control for any streaming sound output device - -#include "quakedef.h" - -#ifdef _WIN32 -#include "winquake.h" -#endif - -void S_Play(void); -void S_PlayVol(void); -void S_SoundList(void); -void S_Update_(); -void S_StopAllSounds(qboolean clear); -void S_StopAllSoundsC(void); - -// ======================================================================= -// Internal sound data & structures -// ======================================================================= - -channel_t channels[MAX_CHANNELS]; -int total_channels; - -int snd_blocked = 0; -static qboolean snd_ambient = 1; -qboolean snd_initialized = false; - -// pointer should go away -volatile dma_t *shm = 0; -volatile dma_t sn; - -vec3_t listener_origin; -vec3_t listener_forward; -vec3_t listener_right; -vec3_t listener_up; -vec_t sound_nominal_clip_dist=1000.0; - -int soundtime; // sample PAIRS -int paintedtime; // sample PAIRS - - -#define MAX_SFX 512 -sfx_t *known_sfx; // hunk allocated [MAX_SFX] -int num_sfx; - -sfx_t *ambient_sfx[NUM_AMBIENTS]; - -int desired_speed = 11025; -int desired_bits = 16; - -int sound_started=0; - -cvar_t bgmvolume = {"bgmvolume", "1", true}; -cvar_t volume = {"volume", "0.7", true}; - -cvar_t nosound = {"nosound", "0"}; -cvar_t precache = {"precache", "1"}; -cvar_t loadas8bit = {"loadas8bit", "0"}; -cvar_t bgmbuffer = {"bgmbuffer", "4096"}; -cvar_t ambient_level = {"ambient_level", "0.3"}; -cvar_t ambient_fade = {"ambient_fade", "100"}; -cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"}; -cvar_t snd_show = {"snd_show", "0"}; -cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true}; - - -// ==================================================================== -// User-setable variables -// ==================================================================== - - -// -// Fake dma is a synchronous faking of the DMA progress used for -// isolating performance in the renderer. The fakedma_updates is -// number of times S_Update() is called per second. -// - -qboolean fakedma = false; -int fakedma_updates = 15; - - -void S_AmbientOff (void) -{ - snd_ambient = false; -} - - -void S_AmbientOn (void) -{ - snd_ambient = true; -} - - -void S_SoundInfo_f(void) -{ - if (!sound_started || !shm) - { - Con_Printf ("sound system not started\n"); - return; - } - - Con_Printf("%5d stereo\n", shm->channels - 1); - Con_Printf("%5d samples\n", shm->samples); - Con_Printf("%5d samplepos\n", shm->samplepos); - Con_Printf("%5d samplebits\n", shm->samplebits); - Con_Printf("%5d submission_chunk\n", shm->submission_chunk); - Con_Printf("%5d speed\n", shm->speed); - Con_Printf("0x%x dma buffer\n", shm->buffer); - Con_Printf("%5d total_channels\n", total_channels); -} - - -/* -================ -S_Startup -================ -*/ - -void S_Startup (void) -{ - int rc; - - if (!snd_initialized) - return; - - if (!fakedma) - { - rc = SNDDMA_Init(); - - if (!rc) - { -#ifndef _WIN32 - Con_Printf("S_Startup: SNDDMA_Init failed.\n"); -#endif - sound_started = 0; - return; - } - } - - sound_started = 1; -} - - -/* -================ -S_Init -================ -*/ -void S_Init (void) -{ - - Con_Printf("\nSound Initialization\n"); - - if (COM_CheckParm("-nosound")) - return; - - if (COM_CheckParm("-simsound")) - fakedma = true; - - Cmd_AddCommand("play", S_Play); - Cmd_AddCommand("playvol", S_PlayVol); - Cmd_AddCommand("stopsound", S_StopAllSoundsC); - Cmd_AddCommand("soundlist", S_SoundList); - Cmd_AddCommand("soundinfo", S_SoundInfo_f); - - Cvar_RegisterVariable(&nosound); - Cvar_RegisterVariable(&volume); - Cvar_RegisterVariable(&precache); - Cvar_RegisterVariable(&loadas8bit); - Cvar_RegisterVariable(&bgmvolume); - Cvar_RegisterVariable(&bgmbuffer); - Cvar_RegisterVariable(&ambient_level); - Cvar_RegisterVariable(&ambient_fade); - Cvar_RegisterVariable(&snd_noextraupdate); - Cvar_RegisterVariable(&snd_show); - Cvar_RegisterVariable(&_snd_mixahead); - - if (host_parms.memsize < 0x800000) - { - Cvar_Set ("loadas8bit", "1"); - Con_Printf ("loading all sounds as 8bit\n"); - } - - - - snd_initialized = true; - - S_Startup (); - - SND_InitScaletable (); - - known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t"); - num_sfx = 0; - -// create a piece of DMA memory - - if (fakedma) - { - shm = (void *) Hunk_AllocName(sizeof(*shm), "shm"); - shm->splitbuffer = 0; - shm->samplebits = 16; - shm->speed = 22050; - shm->channels = 2; - shm->samples = 32768; - shm->samplepos = 0; - shm->soundalive = true; - shm->gamealive = true; - shm->submission_chunk = 1; - shm->buffer = Hunk_AllocName(1<<16, "shmbuf"); - } - - Con_Printf ("Sound sampling rate: %i\n", shm->speed); - - // provides a tick sound until washed clean - -// if (shm->buffer) -// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging - - ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); - ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); - - S_StopAllSounds (true); -} - - -// ======================================================================= -// Shutdown sound engine -// ======================================================================= - -void S_Shutdown(void) -{ - - if (!sound_started) - return; - - if (shm) - shm->gamealive = 0; - - shm = 0; - sound_started = 0; - - if (!fakedma) - { - SNDDMA_Shutdown(); - } -} - - -// ======================================================================= -// Load a sound -// ======================================================================= - -/* -================== -S_FindName - -================== -*/ -sfx_t *S_FindName (char *name) -{ - int i; - sfx_t *sfx; - - if (!name) - Sys_Error ("S_FindName: NULL\n"); - - if (Q_strlen(name) >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", name); - -// see if already loaded - for (i=0 ; i < num_sfx ; i++) - if (!Q_strcmp(known_sfx[i].name, name)) - { - return &known_sfx[i]; - } - - if (num_sfx == MAX_SFX) - Sys_Error ("S_FindName: out of sfx_t"); - - sfx = &known_sfx[i]; - strcpy (sfx->name, name); - - num_sfx++; - - return sfx; -} - - -/* -================== -S_TouchSound - -================== -*/ -void S_TouchSound (char *name) -{ - sfx_t *sfx; - - if (!sound_started) - return; - - sfx = S_FindName (name); - Cache_Check (&sfx->cache); -} - -/* -================== -S_PrecacheSound - -================== -*/ -sfx_t *S_PrecacheSound (char *name) -{ - sfx_t *sfx; - - if (!sound_started || nosound.value) - return NULL; - - sfx = S_FindName (name); - -// cache it in - if (precache.value) - S_LoadSound (sfx); - - return sfx; -} - - -//============================================================================= - -/* -================= -SND_PickChannel -================= -*/ -channel_t *SND_PickChannel(int entnum, int entchannel) -{ - int ch_idx; - int first_to_die; - int life_left; - -// Check for replacement sound, or find the best one to replace - first_to_die = -1; - life_left = 0x7fffffff; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) - { - if (entchannel != 0 // channel 0 never overrides - && channels[ch_idx].entnum == entnum - && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) - { // allways override sound from same entity - first_to_die = ch_idx; - break; - } - - // don't let monster sounds override player sounds - if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx) - continue; - - if (channels[ch_idx].end - paintedtime < life_left) - { - life_left = channels[ch_idx].end - paintedtime; - first_to_die = ch_idx; - } - } - - if (first_to_die == -1) - return NULL; - - if (channels[first_to_die].sfx) - channels[first_to_die].sfx = NULL; - - return &channels[first_to_die]; -} - -/* -================= -SND_Spatialize -================= -*/ -void SND_Spatialize(channel_t *ch) -{ - vec_t dot; - vec_t ldist, rdist, dist; - vec_t lscale, rscale, scale; - vec3_t source_vec; - sfx_t *snd; - -// anything coming from the view entity will allways be full volume - if (ch->entnum == cl.viewentity) - { - ch->leftvol = ch->master_vol; - ch->rightvol = ch->master_vol; - return; - } - -// calculate stereo seperation and distance attenuation - - snd = ch->sfx; - VectorSubtract(ch->origin, listener_origin, source_vec); - - dist = VectorNormalize(source_vec) * ch->dist_mult; - - dot = DotProduct(listener_right, source_vec); - - if (shm->channels == 1) - { - rscale = 1.0; - lscale = 1.0; - } - else - { - rscale = 1.0 + dot; - lscale = 1.0 - dot; - } - -// add in distance effect - scale = (1.0 - dist) * rscale; - ch->rightvol = (int) (ch->master_vol * scale); - if (ch->rightvol < 0) - ch->rightvol = 0; - - scale = (1.0 - dist) * lscale; - ch->leftvol = (int) (ch->master_vol * scale); - if (ch->leftvol < 0) - ch->leftvol = 0; -} - - -// ======================================================================= -// Start a sound effect -// ======================================================================= - -void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) -{ - channel_t *target_chan, *check; - sfxcache_t *sc; - int vol; - int ch_idx; - int skip; - - if (!sound_started) - return; - - if (!sfx) - return; - - if (nosound.value) - return; - - vol = fvol*255; - -// pick a channel to play on - target_chan = SND_PickChannel(entnum, entchannel); - if (!target_chan) - return; - -// spatialize - memset (target_chan, 0, sizeof(*target_chan)); - VectorCopy(origin, target_chan->origin); - target_chan->dist_mult = attenuation / sound_nominal_clip_dist; - target_chan->master_vol = vol; - target_chan->entnum = entnum; - target_chan->entchannel = entchannel; - SND_Spatialize(target_chan); - - if (!target_chan->leftvol && !target_chan->rightvol) - return; // not audible at all - -// new channel - sc = S_LoadSound (sfx); - if (!sc) - { - target_chan->sfx = NULL; - return; // couldn't load the sound's data - } - - target_chan->sfx = sfx; - target_chan->pos = 0.0; - target_chan->end = paintedtime + sc->length; - -// if an identical sound has also been started this frame, offset the pos -// a bit to keep it from just making the first one louder - check = &channels[NUM_AMBIENTS]; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) - { - if (check == target_chan) - continue; - if (check->sfx == sfx && !check->pos) - { - skip = rand () % (int)(0.1*shm->speed); - if (skip >= target_chan->end) - skip = target_chan->end - 1; - target_chan->pos += skip; - target_chan->end -= skip; - break; - } - - } -} - -void S_StopSound(int entnum, int entchannel) -{ - int i; - - for (i=0 ; ibuffer && !pDSBuf)) -#else - if (!sound_started || !shm || !shm->buffer) -#endif - return; - - if (shm->samplebits == 8) - clear = 0x80; - else - clear = 0; - -#ifdef _WIN32 - if (pDSBuf) - { - DWORD dwSize; - DWORD *pData; - int reps; - HRESULT hresult; - - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n"); - S_Shutdown (); - return; - } - } - - Q_memset(pData, clear, shm->samples * shm->samplebits/8); - - pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0); - - } - else -#endif - { - Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8); - } -} - - -/* -================= -S_StaticSound -================= -*/ -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) -{ - channel_t *ss; - sfxcache_t *sc; - - if (!sfx) - return; - - if (total_channels == MAX_CHANNELS) - { - Con_Printf ("total_channels == MAX_CHANNELS\n"); - return; - } - - ss = &channels[total_channels]; - total_channels++; - - sc = S_LoadSound (sfx); - if (!sc) - return; - - if (sc->loopstart == -1) - { - Con_Printf ("Sound %s not looped\n", sfx->name); - return; - } - - ss->sfx = sfx; - VectorCopy (origin, ss->origin); - ss->master_vol = vol; - ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; - ss->end = paintedtime + sc->length; - - SND_Spatialize (ss); -} - - -//============================================================================= - -/* -=================== -S_UpdateAmbientSounds -=================== -*/ -void S_UpdateAmbientSounds (void) -{ - mleaf_t *l; - float vol; - int ambient_channel; - channel_t *chan; - - if (!snd_ambient) - return; - -// calc ambient sound levels - if (!cl.worldmodel) - return; - - l = Mod_PointInLeaf (listener_origin, cl.worldmodel); - if (!l || !ambient_level.value) - { - for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) - channels[ambient_channel].sfx = NULL; - return; - } - - for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) - { - chan = &channels[ambient_channel]; - chan->sfx = ambient_sfx[ambient_channel]; - - vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; - if (vol < 8) - vol = 0; - - // don't adjust volume too fast - if (chan->master_vol < vol) - { - chan->master_vol += host_frametime * ambient_fade.value; - if (chan->master_vol > vol) - chan->master_vol = vol; - } - else if (chan->master_vol > vol) - { - chan->master_vol -= host_frametime * ambient_fade.value; - if (chan->master_vol < vol) - chan->master_vol = vol; - } - - chan->leftvol = chan->rightvol = chan->master_vol; - } -} - - -/* -============ -S_Update - -Called once each time through the main loop -============ -*/ -void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) -{ - int i, j; - int total; - channel_t *ch; - channel_t *combine; - - if (!sound_started || (snd_blocked > 0)) - return; - - VectorCopy(origin, listener_origin); - VectorCopy(forward, listener_forward); - VectorCopy(right, listener_right); - VectorCopy(up, listener_up); - -// update general area ambient sound sources - S_UpdateAmbientSounds (); - - combine = NULL; - -// update spatialization for static and dynamic sounds - ch = channels+NUM_AMBIENTS; - for (i=NUM_AMBIENTS ; isfx) - continue; - SND_Spatialize(ch); // respatialize channel - if (!ch->leftvol && !ch->rightvol) - continue; - - // try to combine static sounds with a previous channel of the same - // sound effect so we don't mix five torches every frame - - if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) - { - // see if it can just use the last one - if (combine && combine->sfx == ch->sfx) - { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; - continue; - } - // search for one - combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; - for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; jsfx == ch->sfx) - break; - - if (j == total_channels) - { - combine = NULL; - } - else - { - if (combine != ch) - { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; - } - continue; - } - } - - - } - -// -// debugging output -// - if (snd_show.value) - { - total = 0; - ch = channels; - for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) - { - //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); - total++; - } - - Con_Printf ("----(%i)----\n", total); - } - -// mix some sound - S_Update_(); -} - -void GetSoundtime(void) -{ - int samplepos; - static int buffers; - static int oldsamplepos; - int fullsamples; - - fullsamples = shm->samples / shm->channels; - -// it is possible to miscount buffers if it has wrapped twice between -// calls to S_Update. Oh well. -#ifdef __sun__ - soundtime = SNDDMA_GetSamples(); -#else - samplepos = SNDDMA_GetDMAPos(); - - - if (samplepos < oldsamplepos) - { - buffers++; // buffer wrapped - - if (paintedtime > 0x40000000) - { // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds (true); - } - } - oldsamplepos = samplepos; - - soundtime = buffers*fullsamples + samplepos/shm->channels; -#endif -} - -void S_ExtraUpdate (void) -{ - -#ifdef _WIN32 - IN_Accumulate (); -#endif - - if (snd_noextraupdate.value) - return; // don't pollute timings - S_Update_(); -} - -void S_Update_(void) -{ - unsigned endtime; - int samps; - - if (!sound_started || (snd_blocked > 0)) - return; - -// Updates DMA time - GetSoundtime(); - -// check to make sure that we haven't overshot - if (paintedtime < soundtime) - { - //Con_Printf ("S_Update_ : overflow\n"); - paintedtime = soundtime; - } - -// mix ahead of current position - endtime = soundtime + _snd_mixahead.value * shm->speed; - samps = shm->samples >> (shm->channels-1); - if (endtime - soundtime > samps) - endtime = soundtime + samps; - -#ifdef _WIN32 -// if the buffer was lost or stopped, restore it and/or restart it - { - DWORD dwStatus; - - if (pDSBuf) - { - if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK) - Con_Printf ("Couldn't get sound buffer status\n"); - - if (dwStatus & DSBSTATUS_BUFFERLOST) - pDSBuf->lpVtbl->Restore (pDSBuf); - - if (!(dwStatus & DSBSTATUS_PLAYING)) - pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - } - } -#endif - - S_PaintChannels (endtime); - - SNDDMA_Submit (); -} - -/* -=============================================================================== - -console functions - -=============================================================================== -*/ - -void S_Play(void) -{ - static int hash=345; - int i; - char name[256]; - sfx_t *sfx; - - i = 1; - while (icache); - if (!sc) - continue; - size = sc->length*sc->width*(sc->stereo+1); - total += size; - if (sc->loopstart >= 0) - Con_Printf ("L"); - else - Con_Printf (" "); - Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name); - } - Con_Printf ("Total resident: %i\n", total); -} - - -void S_LocalSound (char *sound) -{ - sfx_t *sfx; - - if (nosound.value) - return; - if (!sound_started) - return; - - sfx = S_PrecacheSound (sound); - if (!sfx) - { - Con_Printf ("S_LocalSound: can't cache %s\n", sound); - return; - } - S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); -} - - -void S_ClearPrecache (void) -{ -} - - -void S_BeginPrecaching (void) -{ -} - - -void S_EndPrecaching (void) -{ -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// snd_dma.c -- main control for any streaming sound output device + +#include "quakedef.h" + +#ifdef _WIN32 +#include "winquake.h" +#endif + +void S_Play(void); +void S_PlayVol(void); +void S_SoundList(void); +void S_Update_(); +void S_StopAllSounds(qboolean clear); +void S_StopAllSoundsC(void); + +// ======================================================================= +// Internal sound data & structures +// ======================================================================= + +channel_t channels[MAX_CHANNELS]; +int total_channels; + +int snd_blocked = 0; +static qboolean snd_ambient = 1; +qboolean snd_initialized = false; + +// pointer should go away +volatile dma_t *shm = 0; +volatile dma_t sn; + +vec3_t listener_origin; +vec3_t listener_forward; +vec3_t listener_right; +vec3_t listener_up; +vec_t sound_nominal_clip_dist=1000.0; + +int soundtime; // sample PAIRS +int paintedtime; // sample PAIRS + + +#define MAX_SFX 512 +sfx_t *known_sfx; // hunk allocated [MAX_SFX] +int num_sfx; + +sfx_t *ambient_sfx[NUM_AMBIENTS]; + +int desired_speed = 11025; +int desired_bits = 16; + +int sound_started=0; + +cvar_t bgmvolume = {"bgmvolume", "1", true}; +cvar_t volume = {"volume", "0.7", true}; + +cvar_t nosound = {"nosound", "0"}; +cvar_t precache = {"precache", "1"}; +cvar_t loadas8bit = {"loadas8bit", "0"}; +cvar_t bgmbuffer = {"bgmbuffer", "4096"}; +cvar_t ambient_level = {"ambient_level", "0.3"}; +cvar_t ambient_fade = {"ambient_fade", "100"}; +cvar_t snd_noextraupdate = {"snd_noextraupdate", "0"}; +cvar_t snd_show = {"snd_show", "0"}; +cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true}; + + +// ==================================================================== +// User-setable variables +// ==================================================================== + + +// +// Fake dma is a synchronous faking of the DMA progress used for +// isolating performance in the renderer. The fakedma_updates is +// number of times S_Update() is called per second. +// + +qboolean fakedma = false; +int fakedma_updates = 15; + + +void S_AmbientOff (void) +{ + snd_ambient = false; +} + + +void S_AmbientOn (void) +{ + snd_ambient = true; +} + + +void S_SoundInfo_f(void) +{ + if (!sound_started || !shm) + { + Con_Printf ("sound system not started\n"); + return; + } + + Con_Printf("%5d stereo\n", shm->channels - 1); + Con_Printf("%5d samples\n", shm->samples); + Con_Printf("%5d samplepos\n", shm->samplepos); + Con_Printf("%5d samplebits\n", shm->samplebits); + Con_Printf("%5d submission_chunk\n", shm->submission_chunk); + Con_Printf("%5d speed\n", shm->speed); + Con_Printf("0x%x dma buffer\n", shm->buffer); + Con_Printf("%5d total_channels\n", total_channels); +} + + +/* +================ +S_Startup +================ +*/ + +void S_Startup (void) +{ + int rc; + + if (!snd_initialized) + return; + + if (!fakedma) + { + rc = SNDDMA_Init(); + + if (!rc) + { +#ifndef _WIN32 + Con_Printf("S_Startup: SNDDMA_Init failed.\n"); +#endif + sound_started = 0; + return; + } + } + + sound_started = 1; +} + + +/* +================ +S_Init +================ +*/ +void S_Init (void) +{ + + Con_Printf("\nSound Initialization\n"); + + if (COM_CheckParm("-nosound")) + return; + + if (COM_CheckParm("-simsound")) + fakedma = true; + + Cmd_AddCommand("play", S_Play); + Cmd_AddCommand("playvol", S_PlayVol); + Cmd_AddCommand("stopsound", S_StopAllSoundsC); + Cmd_AddCommand("soundlist", S_SoundList); + Cmd_AddCommand("soundinfo", S_SoundInfo_f); + + Cvar_RegisterVariable(&nosound); + Cvar_RegisterVariable(&volume); + Cvar_RegisterVariable(&precache); + Cvar_RegisterVariable(&loadas8bit); + Cvar_RegisterVariable(&bgmvolume); + Cvar_RegisterVariable(&bgmbuffer); + Cvar_RegisterVariable(&ambient_level); + Cvar_RegisterVariable(&ambient_fade); + Cvar_RegisterVariable(&snd_noextraupdate); + Cvar_RegisterVariable(&snd_show); + Cvar_RegisterVariable(&_snd_mixahead); + + if (host_parms.memsize < 0x800000) + { + Cvar_Set ("loadas8bit", "1"); + Con_Printf ("loading all sounds as 8bit\n"); + } + + + + snd_initialized = true; + + S_Startup (); + + SND_InitScaletable (); + + known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t"); + num_sfx = 0; + +// create a piece of DMA memory + + if (fakedma) + { + shm = (void *) Hunk_AllocName(sizeof(*shm), "shm"); + shm->splitbuffer = 0; + shm->samplebits = 16; + shm->speed = 22050; + shm->channels = 2; + shm->samples = 32768; + shm->samplepos = 0; + shm->soundalive = true; + shm->gamealive = true; + shm->submission_chunk = 1; + shm->buffer = Hunk_AllocName(1<<16, "shmbuf"); + } + + Con_Printf ("Sound sampling rate: %i\n", shm->speed); + + // provides a tick sound until washed clean + +// if (shm->buffer) +// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging + + ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); + ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); + + S_StopAllSounds (true); +} + + +// ======================================================================= +// Shutdown sound engine +// ======================================================================= + +void S_Shutdown(void) +{ + + if (!sound_started) + return; + + if (shm) + shm->gamealive = 0; + + shm = 0; + sound_started = 0; + + if (!fakedma) + { + SNDDMA_Shutdown(); + } +} + + +// ======================================================================= +// Load a sound +// ======================================================================= + +/* +================== +S_FindName + +================== +*/ +sfx_t *S_FindName (char *name) +{ + int i; + sfx_t *sfx; + + if (!name) + Sys_Error ("S_FindName: NULL\n"); + + if (Q_strlen(name) >= MAX_QPATH) + Sys_Error ("Sound name too long: %s", name); + +// see if already loaded + for (i=0 ; i < num_sfx ; i++) + if (!Q_strcmp(known_sfx[i].name, name)) + { + return &known_sfx[i]; + } + + if (num_sfx == MAX_SFX) + Sys_Error ("S_FindName: out of sfx_t"); + + sfx = &known_sfx[i]; + strcpy (sfx->name, name); + + num_sfx++; + + return sfx; +} + + +/* +================== +S_TouchSound + +================== +*/ +void S_TouchSound (char *name) +{ + sfx_t *sfx; + + if (!sound_started) + return; + + sfx = S_FindName (name); + Cache_Check (&sfx->cache); +} + +/* +================== +S_PrecacheSound + +================== +*/ +sfx_t *S_PrecacheSound (char *name) +{ + sfx_t *sfx; + + if (!sound_started || nosound.value) + return NULL; + + sfx = S_FindName (name); + +// cache it in + if (precache.value) + S_LoadSound (sfx); + + return sfx; +} + + +//============================================================================= + +/* +================= +SND_PickChannel +================= +*/ +channel_t *SND_PickChannel(int entnum, int entchannel) +{ + int ch_idx; + int first_to_die; + int life_left; + +// Check for replacement sound, or find the best one to replace + first_to_die = -1; + life_left = 0x7fffffff; + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++) + { + if (entchannel != 0 // channel 0 never overrides + && channels[ch_idx].entnum == entnum + && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) + { // allways override sound from same entity + first_to_die = ch_idx; + break; + } + + // don't let monster sounds override player sounds + if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx) + continue; + + if (channels[ch_idx].end - paintedtime < life_left) + { + life_left = channels[ch_idx].end - paintedtime; + first_to_die = ch_idx; + } + } + + if (first_to_die == -1) + return NULL; + + if (channels[first_to_die].sfx) + channels[first_to_die].sfx = NULL; + + return &channels[first_to_die]; +} + +/* +================= +SND_Spatialize +================= +*/ +void SND_Spatialize(channel_t *ch) +{ + vec_t dot; + vec_t ldist, rdist, dist; + vec_t lscale, rscale, scale; + vec3_t source_vec; + sfx_t *snd; + +// anything coming from the view entity will allways be full volume + if (ch->entnum == cl.viewentity) + { + ch->leftvol = ch->master_vol; + ch->rightvol = ch->master_vol; + return; + } + +// calculate stereo seperation and distance attenuation + + snd = ch->sfx; + VectorSubtract(ch->origin, listener_origin, source_vec); + + dist = VectorNormalize(source_vec) * ch->dist_mult; + + dot = DotProduct(listener_right, source_vec); + + if (shm->channels == 1) + { + rscale = 1.0; + lscale = 1.0; + } + else + { + rscale = 1.0 + dot; + lscale = 1.0 - dot; + } + +// add in distance effect + scale = (1.0 - dist) * rscale; + ch->rightvol = (int) (ch->master_vol * scale); + if (ch->rightvol < 0) + ch->rightvol = 0; + + scale = (1.0 - dist) * lscale; + ch->leftvol = (int) (ch->master_vol * scale); + if (ch->leftvol < 0) + ch->leftvol = 0; +} + + +// ======================================================================= +// Start a sound effect +// ======================================================================= + +void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +{ + channel_t *target_chan, *check; + sfxcache_t *sc; + int vol; + int ch_idx; + int skip; + + if (!sound_started) + return; + + if (!sfx) + return; + + if (nosound.value) + return; + + vol = fvol*255; + +// pick a channel to play on + target_chan = SND_PickChannel(entnum, entchannel); + if (!target_chan) + return; + +// spatialize + memset (target_chan, 0, sizeof(*target_chan)); + VectorCopy(origin, target_chan->origin); + target_chan->dist_mult = attenuation / sound_nominal_clip_dist; + target_chan->master_vol = vol; + target_chan->entnum = entnum; + target_chan->entchannel = entchannel; + SND_Spatialize(target_chan); + + if (!target_chan->leftvol && !target_chan->rightvol) + return; // not audible at all + +// new channel + sc = S_LoadSound (sfx); + if (!sc) + { + target_chan->sfx = NULL; + return; // couldn't load the sound's data + } + + target_chan->sfx = sfx; + target_chan->pos = 0.0; + target_chan->end = paintedtime + sc->length; + +// if an identical sound has also been started this frame, offset the pos +// a bit to keep it from just making the first one louder + check = &channels[NUM_AMBIENTS]; + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) + { + if (check == target_chan) + continue; + if (check->sfx == sfx && !check->pos) + { + skip = rand () % (int)(0.1*shm->speed); + if (skip >= target_chan->end) + skip = target_chan->end - 1; + target_chan->pos += skip; + target_chan->end -= skip; + break; + } + + } +} + +void S_StopSound(int entnum, int entchannel) +{ + int i; + + for (i=0 ; ibuffer && !pDSBuf)) +#else + if (!sound_started || !shm || !shm->buffer) +#endif + return; + + if (shm->samplebits == 8) + clear = 0x80; + else + clear = 0; + +#ifdef _WIN32 + if (pDSBuf) + { + DWORD dwSize; + DWORD *pData; + int reps; + HRESULT hresult; + + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pData, &dwSize, NULL, NULL, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_ClearBuffer: DS: couldn't restore buffer\n"); + S_Shutdown (); + return; + } + } + + Q_memset(pData, clear, shm->samples * shm->samplebits/8); + + pDSBuf->lpVtbl->Unlock(pDSBuf, pData, dwSize, NULL, 0); + + } + else +#endif + { + Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8); + } +} + + +/* +================= +S_StaticSound +================= +*/ +void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) +{ + channel_t *ss; + sfxcache_t *sc; + + if (!sfx) + return; + + if (total_channels == MAX_CHANNELS) + { + Con_Printf ("total_channels == MAX_CHANNELS\n"); + return; + } + + ss = &channels[total_channels]; + total_channels++; + + sc = S_LoadSound (sfx); + if (!sc) + return; + + if (sc->loopstart == -1) + { + Con_Printf ("Sound %s not looped\n", sfx->name); + return; + } + + ss->sfx = sfx; + VectorCopy (origin, ss->origin); + ss->master_vol = vol; + ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; + ss->end = paintedtime + sc->length; + + SND_Spatialize (ss); +} + + +//============================================================================= + +/* +=================== +S_UpdateAmbientSounds +=================== +*/ +void S_UpdateAmbientSounds (void) +{ + mleaf_t *l; + float vol; + int ambient_channel; + channel_t *chan; + + if (!snd_ambient) + return; + +// calc ambient sound levels + if (!cl.worldmodel) + return; + + l = Mod_PointInLeaf (listener_origin, cl.worldmodel); + if (!l || !ambient_level.value) + { + for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) + channels[ambient_channel].sfx = NULL; + return; + } + + for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) + { + chan = &channels[ambient_channel]; + chan->sfx = ambient_sfx[ambient_channel]; + + vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; + if (vol < 8) + vol = 0; + + // don't adjust volume too fast + if (chan->master_vol < vol) + { + chan->master_vol += host_frametime * ambient_fade.value; + if (chan->master_vol > vol) + chan->master_vol = vol; + } + else if (chan->master_vol > vol) + { + chan->master_vol -= host_frametime * ambient_fade.value; + if (chan->master_vol < vol) + chan->master_vol = vol; + } + + chan->leftvol = chan->rightvol = chan->master_vol; + } +} + + +/* +============ +S_Update + +Called once each time through the main loop +============ +*/ +void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) +{ + int i, j; + int total; + channel_t *ch; + channel_t *combine; + + if (!sound_started || (snd_blocked > 0)) + return; + + VectorCopy(origin, listener_origin); + VectorCopy(forward, listener_forward); + VectorCopy(right, listener_right); + VectorCopy(up, listener_up); + +// update general area ambient sound sources + S_UpdateAmbientSounds (); + + combine = NULL; + +// update spatialization for static and dynamic sounds + ch = channels+NUM_AMBIENTS; + for (i=NUM_AMBIENTS ; isfx) + continue; + SND_Spatialize(ch); // respatialize channel + if (!ch->leftvol && !ch->rightvol) + continue; + + // try to combine static sounds with a previous channel of the same + // sound effect so we don't mix five torches every frame + + if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) + { + // see if it can just use the last one + if (combine && combine->sfx == ch->sfx) + { + combine->leftvol += ch->leftvol; + combine->rightvol += ch->rightvol; + ch->leftvol = ch->rightvol = 0; + continue; + } + // search for one + combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; + for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; jsfx == ch->sfx) + break; + + if (j == total_channels) + { + combine = NULL; + } + else + { + if (combine != ch) + { + combine->leftvol += ch->leftvol; + combine->rightvol += ch->rightvol; + ch->leftvol = ch->rightvol = 0; + } + continue; + } + } + + + } + +// +// debugging output +// + if (snd_show.value) + { + total = 0; + ch = channels; + for (i=0 ; isfx && (ch->leftvol || ch->rightvol) ) + { + //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); + total++; + } + + Con_Printf ("----(%i)----\n", total); + } + +// mix some sound + S_Update_(); +} + +void GetSoundtime(void) +{ + int samplepos; + static int buffers; + static int oldsamplepos; + int fullsamples; + + fullsamples = shm->samples / shm->channels; + +// it is possible to miscount buffers if it has wrapped twice between +// calls to S_Update. Oh well. +#ifdef __sun__ + soundtime = SNDDMA_GetSamples(); +#else + samplepos = SNDDMA_GetDMAPos(); + + + if (samplepos < oldsamplepos) + { + buffers++; // buffer wrapped + + if (paintedtime > 0x40000000) + { // time to chop things off to avoid 32 bit limits + buffers = 0; + paintedtime = fullsamples; + S_StopAllSounds (true); + } + } + oldsamplepos = samplepos; + + soundtime = buffers*fullsamples + samplepos/shm->channels; +#endif +} + +void S_ExtraUpdate (void) +{ + +#ifdef _WIN32 + IN_Accumulate (); +#endif + + if (snd_noextraupdate.value) + return; // don't pollute timings + S_Update_(); +} + +void S_Update_(void) +{ + unsigned endtime; + int samps; + + if (!sound_started || (snd_blocked > 0)) + return; + +// Updates DMA time + GetSoundtime(); + +// check to make sure that we haven't overshot + if (paintedtime < soundtime) + { + //Con_Printf ("S_Update_ : overflow\n"); + paintedtime = soundtime; + } + +// mix ahead of current position + endtime = soundtime + _snd_mixahead.value * shm->speed; + samps = shm->samples >> (shm->channels-1); + if (endtime - soundtime > samps) + endtime = soundtime + samps; + +#ifdef _WIN32 +// if the buffer was lost or stopped, restore it and/or restart it + { + DWORD dwStatus; + + if (pDSBuf) + { + if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DD_OK) + Con_Printf ("Couldn't get sound buffer status\n"); + + if (dwStatus & DSBSTATUS_BUFFERLOST) + pDSBuf->lpVtbl->Restore (pDSBuf); + + if (!(dwStatus & DSBSTATUS_PLAYING)) + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + } + } +#endif + + S_PaintChannels (endtime); + + SNDDMA_Submit (); +} + +/* +=============================================================================== + +console functions + +=============================================================================== +*/ + +void S_Play(void) +{ + static int hash=345; + int i; + char name[256]; + sfx_t *sfx; + + i = 1; + while (icache); + if (!sc) + continue; + size = sc->length*sc->width*(sc->stereo+1); + total += size; + if (sc->loopstart >= 0) + Con_Printf ("L"); + else + Con_Printf (" "); + Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name); + } + Con_Printf ("Total resident: %i\n", total); +} + + +void S_LocalSound (char *sound) +{ + sfx_t *sfx; + + if (nosound.value) + return; + if (!sound_started) + return; + + sfx = S_PrecacheSound (sound); + if (!sfx) + { + Con_Printf ("S_LocalSound: can't cache %s\n", sound); + return; + } + S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); +} + + +void S_ClearPrecache (void) +{ +} + + +void S_BeginPrecaching (void) +{ +} + + +void S_EndPrecaching (void) +{ +} + diff --git a/WinQuake/snd_dos.c b/WinQuake/snd_dos.c index bcb93b2..a0445cd 100644 --- a/WinQuake/snd_dos.c +++ b/WinQuake/snd_dos.c @@ -1,653 +1,653 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" -#include "dosisms.h" - -int BLASTER_GetDMAPos(void); - -/* -=============================================================================== -GUS SUPPORT - -=============================================================================== -*/ - -qboolean GUS_Init (void); -int GUS_GetDMAPos (void); -void GUS_Shutdown (void); - - -/* -=============================================================================== - -BLASTER SUPPORT - -=============================================================================== -*/ - -short *dma_buffer=0; -static int dma_size; -static int dma; - -static int dsp_port; -static int irq; -static int low_dma; -static int high_dma; -static int mixer_port; -static int mpu401_port; - -int dsp_version; -int dsp_minor_version; - -int timeconstant=-1; - - -void PrintBits (byte b) -{ - int i; - char str[9]; - - for (i=0 ; i<8 ; i++) - str[i] = '0' + ((b & (1<<(7-i))) > 0); - - str[8] = 0; - Con_Printf ("%s (%i)", str, b); -} - -void SB_Info_f(void) -{ - Con_Printf ("BLASTER=%s\n", getenv("BLASTER")); - Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version); - Con_Printf("dma=%d\n", dma); - if (timeconstant != -1) - Con_Printf("timeconstant=%d\n", timeconstant); - Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ()); -} - -// ======================================================================= -// Interprets BLASTER variable -// ======================================================================= - -int GetBLASTER(void) -{ - char *BLASTER; - char *param; - - BLASTER = getenv("BLASTER"); - if (!BLASTER) - return 0; - - param = strchr(BLASTER, 'A'); - if (!param) - param = strchr(BLASTER, 'a'); - if (!param) - return 0; - sscanf(param+1, "%x", &dsp_port); - - param = strchr(BLASTER, 'I'); - if (!param) - param = strchr(BLASTER, 'i'); - if (!param) - return 0; - sscanf(param+1, "%d", &irq); - - param = strchr(BLASTER, 'D'); - if (!param) - param = strchr(BLASTER, 'd'); - if (!param) - return 0; - sscanf(param+1, "%d", &low_dma); - - param = strchr(BLASTER, 'H'); - if (!param) - param = strchr(BLASTER, 'h'); - if (param) - sscanf(param+1, "%d", &high_dma); - - param = strchr(BLASTER, 'M'); - if (!param) - param = strchr(BLASTER, 'm'); - if (param) - sscanf(param+1, "%x", &mixer_port); - else - mixer_port = dsp_port; - - param = strchr(BLASTER, 'P'); - if (!param) - param = strchr(BLASTER, 'p'); - if (param) - sscanf(param+1, "%x", &mpu401_port); - - return 1; - -} - -// ================================================================== -// Resets DSP. Returns 0 on success. -// ================================================================== - -int ResetDSP(void) -{ - volatile int i; - - dos_outportb(dsp_port + 6, 1); - for (i=65536 ; i ; i--) ; - dos_outportb(dsp_port + 6, 0); - for (i=65536 ; i ; i--) - { - if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue; - if (dos_inportb(dsp_port + 0xa) == 0xaa) break; - } - if (i) return 0; - else return 1; - -} - -int ReadDSP(void) -{ - while (!(dos_inportb(dsp_port+0xe)&0x80)) ; - return dos_inportb(dsp_port+0xa); -} - -void WriteDSP(int val) -{ - while ((dos_inportb(dsp_port+0xc)&0x80)) ; - dos_outportb(dsp_port+0xc, val); -} - -int ReadMixer(int addr) -{ - dos_outportb(mixer_port+4, addr); - return dos_inportb(mixer_port+5); -} - -void WriteMixer(int addr, int val) -{ - dos_outportb(mixer_port+4, addr); - dos_outportb(mixer_port+5, val); -} - -int oldmixervalue; - -/* -================ -StartSB - -================ -*/ -void StartSB(void) -{ - int i; - -// version 4.xx startup code - if (dsp_version >= 4) - { - Con_Printf("Version 4 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - WriteDSP(0x41); - - WriteDSP(shm->speed>>8); - WriteDSP(shm->speed&0xff); - - WriteDSP(0xb6); // 16-bit output - WriteDSP(0x30); // stereo - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - } -// version 3.xx startup code - else if (dsp_version == 3) - { - Con_Printf("Version 3 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - oldmixervalue = ReadMixer (0xe); - WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo - - WriteDSP(0x14); // send one byte - WriteDSP(0x0); - WriteDSP(0x0); - - for (i=0 ; i<0x10000 ; i++) - dos_inportb(dsp_port+0xe); // ack the dsp - - timeconstant = 65536-(256000000/(shm->channels*shm->speed)); - WriteDSP(0x40); - WriteDSP(timeconstant>>8); - - WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter - - WriteDSP(0x48); - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - - WriteDSP(0x90); // high speed 8 bit stereo - } -// normal speed mono - else - { - Con_Printf("Version 2 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - timeconstant = 65536-(256000000/(shm->channels*shm->speed)); - WriteDSP(0x40); - WriteDSP(timeconstant>>8); - - WriteDSP(0x48); - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - - WriteDSP(0x1c); // normal speed 8 bit mono - } -} - -static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; -static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc }; -static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce }; - -static int mode_reg; -static int flipflop_reg; -static int disable_reg; -static int clear_reg; - -/* -================ -StartDMA - -================ -*/ -void StartDMA(void) -{ - int mode; - int realaddr; - - realaddr = ptr2real(dma_buffer); - -// use a high dma channel if specified - if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma - dma = high_dma; - else - dma = low_dma; - - Con_Printf ("Using DMA channel %i\n", dma); - - if (dma > 3) - { - mode_reg = 0xd6; - flipflop_reg = 0xd8; - disable_reg = 0xd4; - clear_reg = 0xdc; - } - else - { - mode_reg = 0xb; - flipflop_reg = 0xc; - disable_reg = 0xa; - clear_reg = 0xe; - } - - dos_outportb(disable_reg, dma|4); // disable channel - // set mode- see "undocumented pc", p.876 - mode = (1<<6) // single-cycle - +(0<<5) // address increment - +(1<<4) // auto-init dma - +(2<<2) // read - +(dma&3); // channel # - dos_outportb(mode_reg, mode); - -// set address - // set page - dos_outportb(page_reg[dma], realaddr >> 16); - - if (dma > 3) - { // address is in words - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff); - dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff); - - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff); - dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8); - } - else - { // address is in bytes - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(addr_reg[dma], realaddr & 0xff); - dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff); - - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(count_reg[dma], (dma_size-1) & 0xff); - dos_outportb(count_reg[dma], (dma_size-1) >> 8); - } - - dos_outportb(clear_reg, 0); // clear write mask - dos_outportb(disable_reg, dma&~4); -} - - -/* -================== -BLASTER_Init - -Returns false if nothing is found. -================== -*/ -qboolean BLASTER_Init(void) -{ - int size; - int realaddr; - int rc; - int p; - - shm = 0; - rc = 0; - -// -// must have a blaster variable set -// - if (!GetBLASTER()) - { - Con_NotifyBox ( - "The BLASTER environment variable\n" - "is not set, sound effects are\n" - "disabled. See README.TXT for help.\n" - ); - return 0; - } - - if (ResetDSP()) - { - Con_Printf("Could not reset SB"); - return 0; - } - -// -// get dsp version -// - WriteDSP(0xe1); - dsp_version = ReadDSP(); - dsp_minor_version = ReadDSP(); - -// we need at least v2 for auto-init dma - if (dsp_version < 2) - { - Con_Printf ("Sound blaster must be at least v2.0\n"); - return 0; - } - -// allow command line parm to set quality down - p = COM_CheckParm ("-dsp"); - if (p && p < com_argc - 1) - { - p = Q_atoi (com_argv[p+1]); - if (p < 2 || p > 4) - Con_Printf ("-dsp parameter can only be 2, 3, or 4\n"); - else if (p > dsp_version) - Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version); - else - dsp_version = p; - } - - -// everyone does 11khz sampling rate unless told otherwise - shm = &sn; - shm->speed = 11025; - rc = COM_CheckParm("-sspeed"); - if (rc) - shm->speed = Q_atoi(com_argv[rc+1]); - -// version 4 cards (sb 16) do 16 bit stereo - if (dsp_version >= 4) - { - shm->channels = 2; - shm->samplebits = 16; - } -// version 3 cards (sb pro) do 8 bit stereo - else if (dsp_version == 3) - { - shm->channels = 2; - shm->samplebits = 8; - } -// v2 cards do 8 bit mono - else - { - shm->channels = 1; - shm->samplebits = 8; - } - - - Cmd_AddCommand("sbinfo", SB_Info_f); - size = 4096; - -// allocate 8k and get a 4k-aligned buffer from it - dma_buffer = dos_getmemory(size*2); - if (!dma_buffer) - { - Con_Printf("Couldn't allocate sound dma buffer"); - return false; - } - - realaddr = ptr2real(dma_buffer); - realaddr = (realaddr + size) & ~(size-1); - dma_buffer = (short *) real2ptr(realaddr); - dma_size = size; - - memset(dma_buffer, 0, dma_size); - - shm->soundalive = true; - shm->splitbuffer = false; - - shm->samples = size/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) dma_buffer; - shm->samples = size/(shm->samplebits/8); - - StartDMA(); - StartSB(); - - return true; -} - - -/* -============== -BLASTER_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int BLASTER_GetDMAPos(void) -{ - int count; - -// this function is called often. acknowledge the transfer completions -// all the time so that it loops - if (dsp_version >= 4) - dos_inportb(dsp_port+0xf); // 16 bit audio - else - dos_inportb(dsp_port+0xe); // 8 bit audio - -// clear 16-bit reg flip-flop -// load the current dma count register - if (dma < 4) - { - dos_outportb(0xc, 0); - count = dos_inportb(dma*2+1); - count += dos_inportb(dma*2+1) << 8; - if (shm->samplebits == 16) - count /= 2; - count = shm->samples - (count+1); - } - else - { - dos_outportb(0xd8, 0); - count = dos_inportb(0xc0+(dma-4)*4+2); - count += dos_inportb(0xc0+(dma-4)*4+2) << 8; - if (shm->samplebits == 8) - count *= 2; - count = shm->samples - (count+1); - } - -// Con_Printf("DMA pos = 0x%x\n", count); - - shm->samplepos = count & (shm->samples-1); - return shm->samplepos; - -} - -/* -============== -BLASTER_Shutdown - -Reset the sound device for exiting -=============== -*/ -void BLASTER_Shutdown(void) -{ - if (dsp_version >= 4) - { - } - else if (dsp_version == 3) - { - ResetDSP (); // stop high speed mode - WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on - } - else - { - - } - - WriteDSP(0xd3); // turn off speaker - ResetDSP (); - - dos_outportb(disable_reg, dma|4); // disable dma channel -} - - - -/* -=============================================================================== - -INTERFACE - -=============================================================================== -*/ - -typedef enum -{ - dma_none, - dma_blaster, - dma_gus -} dmacard_t; - -dmacard_t dmacard; - -/* -================== -SNDDM_Init - -Try to find a sound device to mix for. -Returns false if nothing is found. -Returns true and fills in the "shm" structure with information for the mixer. -================== -*/ -qboolean SNDDMA_Init(void) -{ - if (GUS_Init ()) - { - dmacard = dma_gus; - return true; - } - if (BLASTER_Init ()) - { - dmacard = dma_blaster; - return true; - } - - dmacard = dma_none; - - return false; -} - - -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples, not stereo) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos(void) -{ - switch (dmacard) - { - case dma_blaster: - return BLASTER_GetDMAPos (); - case dma_gus: - return GUS_GetDMAPos (); - case dma_none: - break; - } - - return 0; -} - -/* -============== -SNDDMA_Shutdown - -Reset the sound device for exiting -=============== -*/ -void SNDDMA_Shutdown(void) -{ - switch (dmacard) - { - case dma_blaster: - BLASTER_Shutdown (); - break; - case dma_gus: - GUS_Shutdown (); - break; - case dma_none: - break; - } - - dmacard = dma_none; - return; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -=============== -*/ -void SNDDMA_Submit(void) -{ -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" +#include "dosisms.h" + +int BLASTER_GetDMAPos(void); + +/* +=============================================================================== +GUS SUPPORT + +=============================================================================== +*/ + +qboolean GUS_Init (void); +int GUS_GetDMAPos (void); +void GUS_Shutdown (void); + + +/* +=============================================================================== + +BLASTER SUPPORT + +=============================================================================== +*/ + +short *dma_buffer=0; +static int dma_size; +static int dma; + +static int dsp_port; +static int irq; +static int low_dma; +static int high_dma; +static int mixer_port; +static int mpu401_port; + +int dsp_version; +int dsp_minor_version; + +int timeconstant=-1; + + +void PrintBits (byte b) +{ + int i; + char str[9]; + + for (i=0 ; i<8 ; i++) + str[i] = '0' + ((b & (1<<(7-i))) > 0); + + str[8] = 0; + Con_Printf ("%s (%i)", str, b); +} + +void SB_Info_f(void) +{ + Con_Printf ("BLASTER=%s\n", getenv("BLASTER")); + Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version); + Con_Printf("dma=%d\n", dma); + if (timeconstant != -1) + Con_Printf("timeconstant=%d\n", timeconstant); + Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ()); +} + +// ======================================================================= +// Interprets BLASTER variable +// ======================================================================= + +int GetBLASTER(void) +{ + char *BLASTER; + char *param; + + BLASTER = getenv("BLASTER"); + if (!BLASTER) + return 0; + + param = strchr(BLASTER, 'A'); + if (!param) + param = strchr(BLASTER, 'a'); + if (!param) + return 0; + sscanf(param+1, "%x", &dsp_port); + + param = strchr(BLASTER, 'I'); + if (!param) + param = strchr(BLASTER, 'i'); + if (!param) + return 0; + sscanf(param+1, "%d", &irq); + + param = strchr(BLASTER, 'D'); + if (!param) + param = strchr(BLASTER, 'd'); + if (!param) + return 0; + sscanf(param+1, "%d", &low_dma); + + param = strchr(BLASTER, 'H'); + if (!param) + param = strchr(BLASTER, 'h'); + if (param) + sscanf(param+1, "%d", &high_dma); + + param = strchr(BLASTER, 'M'); + if (!param) + param = strchr(BLASTER, 'm'); + if (param) + sscanf(param+1, "%x", &mixer_port); + else + mixer_port = dsp_port; + + param = strchr(BLASTER, 'P'); + if (!param) + param = strchr(BLASTER, 'p'); + if (param) + sscanf(param+1, "%x", &mpu401_port); + + return 1; + +} + +// ================================================================== +// Resets DSP. Returns 0 on success. +// ================================================================== + +int ResetDSP(void) +{ + volatile int i; + + dos_outportb(dsp_port + 6, 1); + for (i=65536 ; i ; i--) ; + dos_outportb(dsp_port + 6, 0); + for (i=65536 ; i ; i--) + { + if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue; + if (dos_inportb(dsp_port + 0xa) == 0xaa) break; + } + if (i) return 0; + else return 1; + +} + +int ReadDSP(void) +{ + while (!(dos_inportb(dsp_port+0xe)&0x80)) ; + return dos_inportb(dsp_port+0xa); +} + +void WriteDSP(int val) +{ + while ((dos_inportb(dsp_port+0xc)&0x80)) ; + dos_outportb(dsp_port+0xc, val); +} + +int ReadMixer(int addr) +{ + dos_outportb(mixer_port+4, addr); + return dos_inportb(mixer_port+5); +} + +void WriteMixer(int addr, int val) +{ + dos_outportb(mixer_port+4, addr); + dos_outportb(mixer_port+5, val); +} + +int oldmixervalue; + +/* +================ +StartSB + +================ +*/ +void StartSB(void) +{ + int i; + +// version 4.xx startup code + if (dsp_version >= 4) + { + Con_Printf("Version 4 SB startup\n"); + WriteDSP(0xd1); // turn on speaker + + WriteDSP(0x41); + + WriteDSP(shm->speed>>8); + WriteDSP(shm->speed&0xff); + + WriteDSP(0xb6); // 16-bit output + WriteDSP(0x30); // stereo + WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 + WriteDSP((shm->samples-1) >> 8); + } +// version 3.xx startup code + else if (dsp_version == 3) + { + Con_Printf("Version 3 SB startup\n"); + WriteDSP(0xd1); // turn on speaker + + oldmixervalue = ReadMixer (0xe); + WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo + + WriteDSP(0x14); // send one byte + WriteDSP(0x0); + WriteDSP(0x0); + + for (i=0 ; i<0x10000 ; i++) + dos_inportb(dsp_port+0xe); // ack the dsp + + timeconstant = 65536-(256000000/(shm->channels*shm->speed)); + WriteDSP(0x40); + WriteDSP(timeconstant>>8); + + WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter + + WriteDSP(0x48); + WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 + WriteDSP((shm->samples-1) >> 8); + + WriteDSP(0x90); // high speed 8 bit stereo + } +// normal speed mono + else + { + Con_Printf("Version 2 SB startup\n"); + WriteDSP(0xd1); // turn on speaker + + timeconstant = 65536-(256000000/(shm->channels*shm->speed)); + WriteDSP(0x40); + WriteDSP(timeconstant>>8); + + WriteDSP(0x48); + WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 + WriteDSP((shm->samples-1) >> 8); + + WriteDSP(0x1c); // normal speed 8 bit mono + } +} + +static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; +static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc }; +static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce }; + +static int mode_reg; +static int flipflop_reg; +static int disable_reg; +static int clear_reg; + +/* +================ +StartDMA + +================ +*/ +void StartDMA(void) +{ + int mode; + int realaddr; + + realaddr = ptr2real(dma_buffer); + +// use a high dma channel if specified + if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma + dma = high_dma; + else + dma = low_dma; + + Con_Printf ("Using DMA channel %i\n", dma); + + if (dma > 3) + { + mode_reg = 0xd6; + flipflop_reg = 0xd8; + disable_reg = 0xd4; + clear_reg = 0xdc; + } + else + { + mode_reg = 0xb; + flipflop_reg = 0xc; + disable_reg = 0xa; + clear_reg = 0xe; + } + + dos_outportb(disable_reg, dma|4); // disable channel + // set mode- see "undocumented pc", p.876 + mode = (1<<6) // single-cycle + +(0<<5) // address increment + +(1<<4) // auto-init dma + +(2<<2) // read + +(dma&3); // channel # + dos_outportb(mode_reg, mode); + +// set address + // set page + dos_outportb(page_reg[dma], realaddr >> 16); + + if (dma > 3) + { // address is in words + dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value + dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff); + dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff); + + dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value + dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff); + dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8); + } + else + { // address is in bytes + dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value + dos_outportb(addr_reg[dma], realaddr & 0xff); + dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff); + + dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value + dos_outportb(count_reg[dma], (dma_size-1) & 0xff); + dos_outportb(count_reg[dma], (dma_size-1) >> 8); + } + + dos_outportb(clear_reg, 0); // clear write mask + dos_outportb(disable_reg, dma&~4); +} + + +/* +================== +BLASTER_Init + +Returns false if nothing is found. +================== +*/ +qboolean BLASTER_Init(void) +{ + int size; + int realaddr; + int rc; + int p; + + shm = 0; + rc = 0; + +// +// must have a blaster variable set +// + if (!GetBLASTER()) + { + Con_NotifyBox ( + "The BLASTER environment variable\n" + "is not set, sound effects are\n" + "disabled. See README.TXT for help.\n" + ); + return 0; + } + + if (ResetDSP()) + { + Con_Printf("Could not reset SB"); + return 0; + } + +// +// get dsp version +// + WriteDSP(0xe1); + dsp_version = ReadDSP(); + dsp_minor_version = ReadDSP(); + +// we need at least v2 for auto-init dma + if (dsp_version < 2) + { + Con_Printf ("Sound blaster must be at least v2.0\n"); + return 0; + } + +// allow command line parm to set quality down + p = COM_CheckParm ("-dsp"); + if (p && p < com_argc - 1) + { + p = Q_atoi (com_argv[p+1]); + if (p < 2 || p > 4) + Con_Printf ("-dsp parameter can only be 2, 3, or 4\n"); + else if (p > dsp_version) + Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version); + else + dsp_version = p; + } + + +// everyone does 11khz sampling rate unless told otherwise + shm = &sn; + shm->speed = 11025; + rc = COM_CheckParm("-sspeed"); + if (rc) + shm->speed = Q_atoi(com_argv[rc+1]); + +// version 4 cards (sb 16) do 16 bit stereo + if (dsp_version >= 4) + { + shm->channels = 2; + shm->samplebits = 16; + } +// version 3 cards (sb pro) do 8 bit stereo + else if (dsp_version == 3) + { + shm->channels = 2; + shm->samplebits = 8; + } +// v2 cards do 8 bit mono + else + { + shm->channels = 1; + shm->samplebits = 8; + } + + + Cmd_AddCommand("sbinfo", SB_Info_f); + size = 4096; + +// allocate 8k and get a 4k-aligned buffer from it + dma_buffer = dos_getmemory(size*2); + if (!dma_buffer) + { + Con_Printf("Couldn't allocate sound dma buffer"); + return false; + } + + realaddr = ptr2real(dma_buffer); + realaddr = (realaddr + size) & ~(size-1); + dma_buffer = (short *) real2ptr(realaddr); + dma_size = size; + + memset(dma_buffer, 0, dma_size); + + shm->soundalive = true; + shm->splitbuffer = false; + + shm->samples = size/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) dma_buffer; + shm->samples = size/(shm->samplebits/8); + + StartDMA(); + StartSB(); + + return true; +} + + +/* +============== +BLASTER_GetDMAPos + +return the current sample position (in mono samples read) +inside the recirculating dma buffer, so the mixing code will know +how many sample are required to fill it up. +=============== +*/ +int BLASTER_GetDMAPos(void) +{ + int count; + +// this function is called often. acknowledge the transfer completions +// all the time so that it loops + if (dsp_version >= 4) + dos_inportb(dsp_port+0xf); // 16 bit audio + else + dos_inportb(dsp_port+0xe); // 8 bit audio + +// clear 16-bit reg flip-flop +// load the current dma count register + if (dma < 4) + { + dos_outportb(0xc, 0); + count = dos_inportb(dma*2+1); + count += dos_inportb(dma*2+1) << 8; + if (shm->samplebits == 16) + count /= 2; + count = shm->samples - (count+1); + } + else + { + dos_outportb(0xd8, 0); + count = dos_inportb(0xc0+(dma-4)*4+2); + count += dos_inportb(0xc0+(dma-4)*4+2) << 8; + if (shm->samplebits == 8) + count *= 2; + count = shm->samples - (count+1); + } + +// Con_Printf("DMA pos = 0x%x\n", count); + + shm->samplepos = count & (shm->samples-1); + return shm->samplepos; + +} + +/* +============== +BLASTER_Shutdown + +Reset the sound device for exiting +=============== +*/ +void BLASTER_Shutdown(void) +{ + if (dsp_version >= 4) + { + } + else if (dsp_version == 3) + { + ResetDSP (); // stop high speed mode + WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on + } + else + { + + } + + WriteDSP(0xd3); // turn off speaker + ResetDSP (); + + dos_outportb(disable_reg, dma|4); // disable dma channel +} + + + +/* +=============================================================================== + +INTERFACE + +=============================================================================== +*/ + +typedef enum +{ + dma_none, + dma_blaster, + dma_gus +} dmacard_t; + +dmacard_t dmacard; + +/* +================== +SNDDM_Init + +Try to find a sound device to mix for. +Returns false if nothing is found. +Returns true and fills in the "shm" structure with information for the mixer. +================== +*/ +qboolean SNDDMA_Init(void) +{ + if (GUS_Init ()) + { + dmacard = dma_gus; + return true; + } + if (BLASTER_Init ()) + { + dmacard = dma_blaster; + return true; + } + + dmacard = dma_none; + + return false; +} + + +/* +============== +SNDDMA_GetDMAPos + +return the current sample position (in mono samples, not stereo) +inside the recirculating dma buffer, so the mixing code will know +how many sample are required to fill it up. +=============== +*/ +int SNDDMA_GetDMAPos(void) +{ + switch (dmacard) + { + case dma_blaster: + return BLASTER_GetDMAPos (); + case dma_gus: + return GUS_GetDMAPos (); + case dma_none: + break; + } + + return 0; +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + switch (dmacard) + { + case dma_blaster: + BLASTER_Shutdown (); + break; + case dma_gus: + GUS_Shutdown (); + break; + case dma_none: + break; + } + + dmacard = dma_none; + return; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(void) +{ +} + diff --git a/WinQuake/snd_gus.c b/WinQuake/snd_gus.c index dd1376f..7c567ca 100644 --- a/WinQuake/snd_gus.c +++ b/WinQuake/snd_gus.c @@ -1,1293 +1,1293 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -//============================================================================= -// Routines for GUS support in QUAKE -// -// Author(s): Jayeson Lee-Steere -//============================================================================= - -#include "quakedef.h" -#include "dosisms.h" - -//============================================================================= -// Author(s): Jayeson Lee-Steere - -#define INI_STRING_SIZE 0x100 - -FILE *ini_fopen(const char *filename, const char *modes); -int ini_fclose(FILE *f); -void ini_fgets(FILE *f, const char *section, const char *field, char *s); - -// Routines for reading from .INI files -// The read routines are fairly efficient. -// -// Author(s): Jayeson Lee-Steere - -#define MAX_SECTION_WIDTH 20 -#define MAX_FIELD_WIDTH 20 - -#define NUM_SECTION_BUFFERS 10 -#define NUM_FIELD_BUFFERS 20 - -struct section_buffer -{ - long offset; - char name[MAX_SECTION_WIDTH+1]; -}; - -struct field_buffer -{ - long offset; - int section; - char name[MAX_FIELD_WIDTH+1]; -}; - -static FILE *current_file=NULL; -static int current_section; - -static int current_section_buffer=0; -static int current_field_buffer=0; - -static struct section_buffer section_buffers[NUM_SECTION_BUFFERS]; -static struct field_buffer field_buffers[NUM_FIELD_BUFFERS]; -//*************************************************************************** -// Internal routines -//*************************************************************************** -static char toupper(char c) -{ - if (c>='a' && c<='z') - c-=('a'-'A'); - return(c); -} - -static void reset_buffer(FILE *f) -{ - int i; - - for (i=0;i0 && out[i-1]==' ') - i--; - // Null terminate the output string. - out[i]=0; -} - -// Extracts the field name from a field line -// e.g. in="sooty=life be in it" gives out="sooty" -static void get_field_name(char *out, char *in) -{ - int i=0; - - // Skip leading spaces - while (in[0]==' ') - in++; - // Copy name to output string - while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0) - { - if (iNUM_SECTION_BUFFERS) - current_section_buffer=0; - // Delete any field buffers that correspond to this section - for (i=0;iNUM_FIELD_BUFFERS) - current_field_buffer=0; - // Set buffer information - strcpy(field_buffers[current_field_buffer].name,field); - field_buffers[current_field_buffer].section=section; - field_buffers[current_field_buffer].offset=offset; -} - -// Identical to fgets except the string is trucated at the first ';', -// carriage return or line feed. -static char *stripped_fgets(char *s, int n, FILE *f) -{ - int i=0; - - if (fgets(s,n,f)==NULL) - return(NULL); - - while (s[i]!=';' && s[i]!=13 && s[i]!=10 && s[i]!=0) - i++; - s[i]=0; - - return(s); -} - -//*************************************************************************** -// Externally accessable routines -//*************************************************************************** -// Opens an .INI file. Works like fopen -FILE *ini_fopen(const char *filename, const char *modes) -{ - return(fopen(filename,modes)); -} - -// Closes a .INI file. Works like fclose -int ini_fclose(FILE *f) -{ - if (f==current_file) - reset_buffer(NULL); - return(fclose(f)); -} - -// Puts "field" from "section" from .ini file "f" into "s". -// If "section" does not exist or "field" does not exist in -// section then s=""; -void ini_fgets(FILE *f, const char *section, const char *field, char *s) -{ - int i; - long start_pos,string_start_pos; - char ts[INI_STRING_SIZE*2]; - - if (f!=current_file) - reset_buffer(f); - - // Default to "Not found" - s[0]=0; - - // See if section is in buffer - for (i=0;i>1) & 0x0001FFFF) | (Address & 0x000C0000L) ); -} - -void ClearGf1Ints(void) -{ - int i; - - SetGf18(DMA_CONTROL,0x00); - SetGf18(ADLIB_CONTROL,0x00); - SetGf18(RECORD_CONTROL,0x00); - - GetGf18(DMA_CONTROL); - GetGf18(RECORD_CONTROL); - for (i=0;i<32;i++); - GetGf18(GET_IRQV); -} - - -//============================================================================= -// Get Interwave (UltraSound PnP) configuration if any -//============================================================================= -static qboolean GUS_GetIWData(void) -{ - char *Interwave,s[INI_STRING_SIZE]; - FILE *IwFile; - int CodecBase,CodecDma,i; - - Interwave=getenv("INTERWAVE"); - if (Interwave==NULL) - return(false); - - // Open IW.INI - IwFile=ini_fopen(Interwave,"rt"); - if (IwFile==NULL) - return(false); - - // Read codec base and codec DMA - ini_fgets(IwFile,"setup 0","CodecBase",s); - sscanf(s,"%X",&CodecBase); - ini_fgets(IwFile,"setup 0","DMA2",s); - sscanf(s,"%i",&CodecDma); - - ini_fclose(IwFile); - - // Make sure numbers OK - if (CodecBase==0 || CodecDma==0) - return(false); - - CodecRegisterSelect=CodecBase; - CodecData=CodecBase+1; - CodecStatus=CodecBase+2; - DmaChannel=CodecDma; - - // Make sure there is a CODEC at the CODEC base - - // Clear any pending IRQs - dos_inportb(CodecStatus); - dos_outportb(CodecStatus,0); - - // Wait for 'INIT' bit to clear - for (i=0;i<0xFFFF;i++) - if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0) - break; - if (i==0xFFFF) - return(false); - - // Get chip revision - can not be zero - dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); - if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID) - return(false); - if ((dos_inportb(CodecData) & 0x0F) == 0) - return(false); - - HaveCodec=1; - Con_Printf("Sound Card is UltraSound PnP\n"); - return(true); -} - -//============================================================================= -// Get UltraSound MAX configuration if any -//============================================================================= -static qboolean GUS_GetMAXData(void) -{ - char *Ultrasnd,*Ultra16; - int i; - int GusBase,Dma1,Dma2,Irq1,Irq2; - int CodecBase,CodecDma,CodecIrq,CodecType; - BYTE MaxVal; - - Ultrasnd=getenv("ULTRASND"); - Ultra16=getenv("ULTRA16"); - if (Ultrasnd==NULL || Ultra16==NULL) - return(false); - - sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2); - sscanf(Ultra16,"%x,%i,%i,%i",&CodecBase,&CodecDma,&CodecIrq,&CodecType); - - if (CodecType==0 && CodecDma!=0) - DmaChannel=CodecDma & 0x07; - else - DmaChannel=Dma2 & 0x07; - - // Make sure there is a GUS at GUS base - dos_outportb(GusBase+0x08,0x55); - if (dos_inportb(GusBase+0x0A)!=0x55) - return(false); - dos_outportb(GusBase+0x08,0xAA); - if (dos_inportb(GusBase+0x0A)!=0xAA) - return(false); - - // Program CODEC control register - MaxVal=((CodecBase & 0xF0)>>4) | 0x40; - if (Dma1 > 3) - MaxVal|=0x10; - if (Dma2 > 3) - MaxVal|=0x20; - dos_outportb(GusBase+0x106,MaxVal); - - CodecRegisterSelect=CodecBase; - CodecData=CodecBase+1; - CodecStatus=CodecBase+2; - - // Make sure there is a CODEC at the CODEC base - - // Clear any pending IRQs - dos_inportb(CodecStatus); - dos_outportb(CodecStatus,0); - - // Wait for 'INIT' bit to clear - for (i=0;i<0xFFFF;i++) - if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0) - break; - if (i==0xFFFF) - return(false); - - // Get chip revision - can not be zero - dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); - if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID) - return(false); - if ((dos_inportb(CodecData) & 0x0F) == 0) - return(false); - - HaveCodec=1; - Con_Printf("Sound Card is UltraSound MAX\n"); - return(true); -} - -//============================================================================= -// Get regular UltraSound configuration if any -//============================================================================= -static qboolean GUS_GetGUSData(void) -{ - char *Ultrasnd; - int GusBase,Dma1,Dma2,Irq1,Irq2,i; - - Ultrasnd=getenv("ULTRASND"); - if (Ultrasnd==NULL) - return(false); - - sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2); - - DmaChannel=Dma1 & 0x07; - - // Make sure there is a GUS at GUS base - dos_outportb(GusBase+0x08,0x55); - if (dos_inportb(GusBase+0x0A)!=0x55) - return(false); - dos_outportb(GusBase+0x08,0xAA); - if (dos_inportb(GusBase+0x0A)!=0xAA) - return(false); - - Gf1TimerControl = GusBase+0x008; - Gf1PageRegister = GusBase+0x102; - Gf1RegisterSelect = GusBase+0x103; - Gf1DataLow = GusBase+0x104; - Gf1DataHigh = GusBase+0x105; - - // Reset the GUS - SetGf18(MASTER_RESET,0x00); - Gf1Delay(); - Gf1Delay(); - SetGf18(MASTER_RESET,0x01); - Gf1Delay(); - Gf1Delay(); - - // Set to max (32) voices - SetGf18(SET_VOICES,0xDF); - - // Clear any pending IRQ's - ClearGf1Ints(); - - // Set all registers to known values - for (i=0;i<32;i++) - { - dos_outportb(Gf1PageRegister,i); - SetGf18(SET_CONTROL,0x03); - SetGf18(SET_VOLUME_CONTROL,0x03); - Gf1Delay(); - SetGf18(SET_CONTROL,0x03); - SetGf18(SET_VOLUME_CONTROL,0x03); - SetGf116(SET_START_HIGH,0); - SetGf116(SET_START_LOW,0); - SetGf116(SET_END_HIGH,0); - SetGf116(SET_END_LOW,0); - SetGf116(SET_ACC_HIGH,0); - SetGf116(SET_ACC_LOW,0); - SetGf18(SET_VOLUME_RATE,63); - SetGf18(SET_VOLUME_START,5); - SetGf18(SET_VOLUME_END,251); - SetGf116(SET_VOLUME,5<<8); - } - - // Clear any pending IRQ's - ClearGf1Ints(); - - // Enable DAC etc. - SetGf18(MASTER_RESET,0x07); - - // Enable line output so we can hear something - dos_outportb(GusBase,0x08); - - HaveCodec=0; - Con_Printf("Sound Card is UltraSound\n"); - return(true); -} - - -//============================================================================= -// Programs the DMA controller to start DMAing in Auto-init mode -//============================================================================= -static void GUS_StartDMA(BYTE DmaChannel,short *dma_buffer,int count) -{ - int mode; - int RealAddr; - - RealAddr = ptr2real(dma_buffer); - - if (DmaChannel <= 3) - { - ModeReg = 0x0B; - DisableReg = 0x0A; - ClearReg = 0x0E; - } - else - { - ModeReg = 0xD6; - DisableReg = 0xD4; - ClearReg = 0xDC; - } - CountReg=CountRegs[DmaChannel]; - AddrReg=AddrRegs[DmaChannel]; - - dos_outportb(DisableReg, DmaChannel | 4); // disable channel - - // set mode- see "undocumented pc", p.876 - mode = (1<<6) // single-cycle - +(0<<5) // address increment - +(1<<4) // auto-init dma - +(2<<2) // read - +(DmaChannel & 0x03); // channel # - dos_outportb(ModeReg, mode); - - // set page - dos_outportb(PageRegs[DmaChannel], RealAddr >> 16); - - if (DmaChannel <= 3) - { // address is in bytes - dos_outportb(0x0C, 0); // prepare to send 16-bit value - dos_outportb(AddrReg, RealAddr & 0xff); - dos_outportb(AddrReg, (RealAddr>>8) & 0xff); - - dos_outportb(0x0C, 0); // prepare to send 16-bit value - dos_outportb(CountReg, (count-1) & 0xff); - dos_outportb(CountReg, (count-1) >> 8); - } - else - { // address is in words - dos_outportb(0xD8, 0); // prepare to send 16-bit value - dos_outportb(AddrReg, (RealAddr>>1) & 0xff); - dos_outportb(AddrReg, (RealAddr>>9) & 0xff); - - dos_outportb(0xD8, 0); // prepare to send 16-bit value - dos_outportb(CountReg, ((count>>1)-1) & 0xff); - dos_outportb(CountReg, ((count>>1)-1) >> 8); - } - - dos_outportb(ClearReg, 0); // clear write mask - dos_outportb(DisableReg, DmaChannel & ~4); -} - -//============================================================================= -// Starts the CODEC playing -//============================================================================= -static void GUS_StartCODEC(int count,BYTE FSVal) -{ - int i,j; - - // Clear any pending IRQs - dos_inportb(CodecStatus); - dos_outportb(CodecStatus,0); - - // Set mode to 2 - dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); - dos_outportb(CodecData,0xC0); - - // Stop any playback or capture which may be happening - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); - dos_outportb(CodecData,dos_inportb(CodecData) & 0xFC); - - // Set FS - dos_outportb(CodecRegisterSelect,CODEC_FS_FORMAT | 0x40); - dos_outportb(CodecData,FSVal | 0x50); // Or in stereo and 16 bit bits - - // Wait a bit - for (i=0;i<10;i++) - dos_inportb(CodecData); - - // Routine 1 to counter CODEC bug - wait for init bit to clear and then a - // bit longer (i=min loop count, j=timeout - for (i=0,j=0;i<1000 && j<0x7FFFF;j++) - if ((dos_inportb(CodecRegisterSelect) & 0x80)==0) - i++; - - // Routine 2 to counter CODEC bug - this is from Forte's code. For me it - // does not seem to cure the problem, but is added security - // Waits till we can modify index register - for (j=0;j<0x7FFFF;j++) - { - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); - if (dos_inportb(CodecRegisterSelect)==(CODEC_INTERFACE_CONFIG | 0x40)) - break; - } - - // Perform ACAL - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); - dos_outportb(CodecData,0x08); - - // Clear MCE bit - this makes ACAL happen - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); - - // Wait for ACAL to finish - for (j=0;j<0x7FFFF;j++) - { - if ((dos_inportb(CodecRegisterSelect) & 0x80) != 0) - continue; - dos_outportb(CodecRegisterSelect,CODEC_ERROR_STATUS_AND_INIT); - if ((dos_inportb(CodecData) & 0x20) == 0) - break; - } - - // Clear ACAL bit - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); - dos_outportb(CodecData,0x00); - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); - - // Set some other junk - dos_outportb(CodecRegisterSelect,CODEC_LOOPBACK_CONTROL); - dos_outportb(CodecData,0x00); - dos_outportb(CodecRegisterSelect,CODEC_PIN_CONTROL); - dos_outportb(CodecData,0x08); // IRQ is disabled in PIN control - - // Set count (it doesn't really matter what value we stuff in here - dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_LOWER_BASE_COUNT); - dos_outportb(CodecData,count & 0xFF); - dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_UPPER_BASE_COUNT); - dos_outportb(CodecData,count >> 8); - - // Start playback - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); - dos_outportb(CodecData,0x01); -} - -//============================================================================= -// Starts the GF1 playing -//============================================================================= -static void GUS_StartGf1(int count,BYTE Voices) -{ - DWORD StartAddressL,EndAddressL,StartAddressR,EndAddressR; - - // Set number of voices to give us the sampling rate we want - SetGf18(SET_VOICES,0xC0 | (Voices-1)); - - // Figure out addresses - StartAddressL=ConvertTo16(0); - EndAddressL=ConvertTo16(count-2-2); - StartAddressR=ConvertTo16(2); - EndAddressR=ConvertTo16(count-2); - - // Set left voice addresses - dos_outportb(Gf1PageRegister,0); - SetGf116(SET_START_LOW,StartAddressL<<9); - SetGf116(SET_START_HIGH,StartAddressL>>7); - SetGf116(SET_ACC_LOW,StartAddressL<<9); - SetGf116(SET_ACC_HIGH,StartAddressL>>7); - SetGf116(SET_END_LOW,EndAddressL<<9); - SetGf116(SET_END_HIGH,EndAddressL>>7); - // Set balance to full left - SetGf18(SET_BALANCE,0); - // Set volume to full - SetGf116(SET_VOLUME,0xFFF0); - // Set FC to 2 (so we play every second sample) - SetGf116(SET_FREQUENCY,0x0800); - - // Set right voice addresses - dos_outportb(Gf1PageRegister,1); - SetGf116(SET_START_LOW,StartAddressR<<9); - SetGf116(SET_START_HIGH,StartAddressR>>7); - SetGf116(SET_ACC_LOW,StartAddressR<<9); - SetGf116(SET_ACC_HIGH,StartAddressR>>7); - SetGf116(SET_END_LOW,EndAddressR<<9); - SetGf116(SET_END_HIGH,EndAddressR>>7); - // Set balance to full right - SetGf18(SET_BALANCE,15); - // Set volume to full - SetGf116(SET_VOLUME,0xFFF0); - // Set FC to 2 (so we play every second sample) - SetGf116(SET_FREQUENCY,0x0800); - - // Start voices - dos_outportb(Gf1PageRegister,0); - SetGf18(SET_CONTROL,0x0C); - dos_outportb(Gf1PageRegister,1); - SetGf18(SET_CONTROL,0x0C); - Gf1Delay(); - dos_outportb(Gf1PageRegister,0); - SetGf18(SET_CONTROL,0x0C); - dos_outportb(Gf1PageRegister,1); - SetGf18(SET_CONTROL,0x0C); -} - - -//============================================================================= -// Figures out what kind of UltraSound we have, if any, and starts it playing -//============================================================================= -qboolean GUS_Init(void) -{ - int rc; - int RealAddr; - BYTE FSVal,Voices; - struct CodecRateStruct *CodecRate; - struct Gf1RateStruct *Gf1Rate; - - // See what kind of UltraSound we have, if any - if (GUS_GetIWData()==false) - if (GUS_GetMAXData()==false) - if (GUS_GetGUSData()==false) - return(false); - - shm = &sn; - - if (HaveCodec) - { - // do 11khz sampling rate unless command line parameter wants different - shm->speed = 11025; - FSVal = 0x03; - rc = COM_CheckParm("-sspeed"); - if (rc) - { - shm->speed = Q_atoi(com_argv[rc+1]); - - // Make sure rate not too high - if (shm->speed>48000) - shm->speed=48000; - - // Adjust speed to match one of the possible CODEC rates - for (CodecRate=CodecRates;CodecRate->Rate!=0;CodecRate++) - { - if (shm->speed <= CodecRate->Rate) - { - shm->speed=CodecRate->Rate; - FSVal=CodecRate->FSVal; - break; - } - } - } - - - // Always do 16 bit stereo - shm->channels = 2; - shm->samplebits = 16; - - // allocate buffer twice the size we need so we can get aligned buffer - dma_buffer = dos_getmemory(BUFFER_SIZE*2); - if (dma_buffer==NULL) - { - Con_Printf("Couldn't allocate sound dma buffer"); - return false; - } - - RealAddr = ptr2real(dma_buffer); - RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1); - dma_buffer = (short *) real2ptr(RealAddr); - - // Zero off DMA buffer - memset(dma_buffer, 0, BUFFER_SIZE); - - shm->soundalive = true; - shm->splitbuffer = false; - - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) dma_buffer; - shm->samples = BUFFER_SIZE/(shm->samplebits/8); - - GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); - GUS_StartCODEC(BUFFER_SIZE,FSVal); - } - else - { - // do 19khz sampling rate unless command line parameter wants different - shm->speed = 19293; - Voices=32; - rc = COM_CheckParm("-sspeed"); - if (rc) - { - shm->speed = Q_atoi(com_argv[rc+1]); - - // Make sure rate not too high - if (shm->speed>44100) - shm->speed=44100; - - // Adjust speed to match one of the possible GF1 rates - for (Gf1Rate=Gf1Rates;Gf1Rate->Rate!=0;Gf1Rate++) - { - if (shm->speed <= Gf1Rate->Rate) - { - shm->speed=Gf1Rate->Rate; - Voices=Gf1Rate->Voices; - break; - } - } - } - - // Always do 16 bit stereo - shm->channels = 2; - shm->samplebits = 16; - - // allocate buffer twice the size we need so we can get aligned buffer - dma_buffer = dos_getmemory(BUFFER_SIZE*2); - if (dma_buffer==NULL) - { - Con_Printf("Couldn't allocate sound dma buffer"); - return false; - } - - RealAddr = ptr2real(dma_buffer); - RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1); - dma_buffer = (short *) real2ptr(RealAddr); - - // Zero off DMA buffer - memset(dma_buffer, 0, BUFFER_SIZE); - - shm->soundalive = true; - shm->splitbuffer = false; - - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) dma_buffer; - shm->samples = BUFFER_SIZE/(shm->samplebits/8); - - GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); - SetGf116(SET_DMA_ADDRESS,0x0000); - if (DmaChannel<=3) - SetGf18(DMA_CONTROL,0x41); - else - SetGf18(DMA_CONTROL,0x45); - GUS_StartGf1(BUFFER_SIZE,Voices); - } - return(true); -} - -//============================================================================= -// Returns the current playback position -//============================================================================= -int GUS_GetDMAPos(void) -{ - int count; - - if (HaveCodec) - { - // clear 16-bit reg flip-flop - // load the current dma count register - if (DmaChannel < 4) - { - dos_outportb(0x0C, 0); - count = dos_inportb(CountReg); - count += dos_inportb(CountReg) << 8; - if (shm->samplebits == 16) - count /= 2; - count = shm->samples - (count+1); - } - else - { - dos_outportb(0xD8, 0); - count = dos_inportb(CountReg); - count += dos_inportb(CountReg) << 8; - if (shm->samplebits == 8) - count *= 2; - count = shm->samples - (count+1); - } - - } - else - { - // Read current position from GF1 - dos_outportb(Gf1PageRegister,0); - count=(GetGf116(GET_ACC_HIGH)<<7) & 0xFFFF; - // See which half of buffer we are in. Note that since this is 16 bit - // data we are playing, position is in 16 bit samples - if (GetGf18(DMA_CONTROL) & 0x40) - { - GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); - SetGf116(SET_DMA_ADDRESS,0x0000); - if (DmaChannel<=3) - SetGf18(DMA_CONTROL,0x41); - else - SetGf18(DMA_CONTROL,0x45); - } - } - - shm->samplepos = count & (shm->samples-1); - return(shm->samplepos); -} - -//============================================================================= -// Stops the UltraSound playback -//============================================================================= -void GUS_Shutdown (void) -{ - if (HaveCodec) - { - // Stop CODEC - dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); - dos_outportb(CodecData,0x01); - } - else - { - // Stop Voices - dos_outportb(Gf1PageRegister,0); - SetGf18(SET_CONTROL,0x03); - dos_outportb(Gf1PageRegister,1); - SetGf18(SET_CONTROL,0x03); - Gf1Delay(); - dos_outportb(Gf1PageRegister,0); - SetGf18(SET_CONTROL,0x03); - dos_outportb(Gf1PageRegister,1); - SetGf18(SET_CONTROL,0x03); - - // Stop any DMA - SetGf18(DMA_CONTROL,0x00); - GetGf18(DMA_CONTROL); - } - - dos_outportb(DisableReg, DmaChannel | 4); // disable dma channel -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +//============================================================================= +// Routines for GUS support in QUAKE +// +// Author(s): Jayeson Lee-Steere +//============================================================================= + +#include "quakedef.h" +#include "dosisms.h" + +//============================================================================= +// Author(s): Jayeson Lee-Steere + +#define INI_STRING_SIZE 0x100 + +FILE *ini_fopen(const char *filename, const char *modes); +int ini_fclose(FILE *f); +void ini_fgets(FILE *f, const char *section, const char *field, char *s); + +// Routines for reading from .INI files +// The read routines are fairly efficient. +// +// Author(s): Jayeson Lee-Steere + +#define MAX_SECTION_WIDTH 20 +#define MAX_FIELD_WIDTH 20 + +#define NUM_SECTION_BUFFERS 10 +#define NUM_FIELD_BUFFERS 20 + +struct section_buffer +{ + long offset; + char name[MAX_SECTION_WIDTH+1]; +}; + +struct field_buffer +{ + long offset; + int section; + char name[MAX_FIELD_WIDTH+1]; +}; + +static FILE *current_file=NULL; +static int current_section; + +static int current_section_buffer=0; +static int current_field_buffer=0; + +static struct section_buffer section_buffers[NUM_SECTION_BUFFERS]; +static struct field_buffer field_buffers[NUM_FIELD_BUFFERS]; +//*************************************************************************** +// Internal routines +//*************************************************************************** +static char toupper(char c) +{ + if (c>='a' && c<='z') + c-=('a'-'A'); + return(c); +} + +static void reset_buffer(FILE *f) +{ + int i; + + for (i=0;i0 && out[i-1]==' ') + i--; + // Null terminate the output string. + out[i]=0; +} + +// Extracts the field name from a field line +// e.g. in="sooty=life be in it" gives out="sooty" +static void get_field_name(char *out, char *in) +{ + int i=0; + + // Skip leading spaces + while (in[0]==' ') + in++; + // Copy name to output string + while (in[0]!='=' && in[0]!=13 && in[0]!=10 && in[0]!=0) + { + if (iNUM_SECTION_BUFFERS) + current_section_buffer=0; + // Delete any field buffers that correspond to this section + for (i=0;iNUM_FIELD_BUFFERS) + current_field_buffer=0; + // Set buffer information + strcpy(field_buffers[current_field_buffer].name,field); + field_buffers[current_field_buffer].section=section; + field_buffers[current_field_buffer].offset=offset; +} + +// Identical to fgets except the string is trucated at the first ';', +// carriage return or line feed. +static char *stripped_fgets(char *s, int n, FILE *f) +{ + int i=0; + + if (fgets(s,n,f)==NULL) + return(NULL); + + while (s[i]!=';' && s[i]!=13 && s[i]!=10 && s[i]!=0) + i++; + s[i]=0; + + return(s); +} + +//*************************************************************************** +// Externally accessable routines +//*************************************************************************** +// Opens an .INI file. Works like fopen +FILE *ini_fopen(const char *filename, const char *modes) +{ + return(fopen(filename,modes)); +} + +// Closes a .INI file. Works like fclose +int ini_fclose(FILE *f) +{ + if (f==current_file) + reset_buffer(NULL); + return(fclose(f)); +} + +// Puts "field" from "section" from .ini file "f" into "s". +// If "section" does not exist or "field" does not exist in +// section then s=""; +void ini_fgets(FILE *f, const char *section, const char *field, char *s) +{ + int i; + long start_pos,string_start_pos; + char ts[INI_STRING_SIZE*2]; + + if (f!=current_file) + reset_buffer(f); + + // Default to "Not found" + s[0]=0; + + // See if section is in buffer + for (i=0;i>1) & 0x0001FFFF) | (Address & 0x000C0000L) ); +} + +void ClearGf1Ints(void) +{ + int i; + + SetGf18(DMA_CONTROL,0x00); + SetGf18(ADLIB_CONTROL,0x00); + SetGf18(RECORD_CONTROL,0x00); + + GetGf18(DMA_CONTROL); + GetGf18(RECORD_CONTROL); + for (i=0;i<32;i++); + GetGf18(GET_IRQV); +} + + +//============================================================================= +// Get Interwave (UltraSound PnP) configuration if any +//============================================================================= +static qboolean GUS_GetIWData(void) +{ + char *Interwave,s[INI_STRING_SIZE]; + FILE *IwFile; + int CodecBase,CodecDma,i; + + Interwave=getenv("INTERWAVE"); + if (Interwave==NULL) + return(false); + + // Open IW.INI + IwFile=ini_fopen(Interwave,"rt"); + if (IwFile==NULL) + return(false); + + // Read codec base and codec DMA + ini_fgets(IwFile,"setup 0","CodecBase",s); + sscanf(s,"%X",&CodecBase); + ini_fgets(IwFile,"setup 0","DMA2",s); + sscanf(s,"%i",&CodecDma); + + ini_fclose(IwFile); + + // Make sure numbers OK + if (CodecBase==0 || CodecDma==0) + return(false); + + CodecRegisterSelect=CodecBase; + CodecData=CodecBase+1; + CodecStatus=CodecBase+2; + DmaChannel=CodecDma; + + // Make sure there is a CODEC at the CODEC base + + // Clear any pending IRQs + dos_inportb(CodecStatus); + dos_outportb(CodecStatus,0); + + // Wait for 'INIT' bit to clear + for (i=0;i<0xFFFF;i++) + if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0) + break; + if (i==0xFFFF) + return(false); + + // Get chip revision - can not be zero + dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); + if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID) + return(false); + if ((dos_inportb(CodecData) & 0x0F) == 0) + return(false); + + HaveCodec=1; + Con_Printf("Sound Card is UltraSound PnP\n"); + return(true); +} + +//============================================================================= +// Get UltraSound MAX configuration if any +//============================================================================= +static qboolean GUS_GetMAXData(void) +{ + char *Ultrasnd,*Ultra16; + int i; + int GusBase,Dma1,Dma2,Irq1,Irq2; + int CodecBase,CodecDma,CodecIrq,CodecType; + BYTE MaxVal; + + Ultrasnd=getenv("ULTRASND"); + Ultra16=getenv("ULTRA16"); + if (Ultrasnd==NULL || Ultra16==NULL) + return(false); + + sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2); + sscanf(Ultra16,"%x,%i,%i,%i",&CodecBase,&CodecDma,&CodecIrq,&CodecType); + + if (CodecType==0 && CodecDma!=0) + DmaChannel=CodecDma & 0x07; + else + DmaChannel=Dma2 & 0x07; + + // Make sure there is a GUS at GUS base + dos_outportb(GusBase+0x08,0x55); + if (dos_inportb(GusBase+0x0A)!=0x55) + return(false); + dos_outportb(GusBase+0x08,0xAA); + if (dos_inportb(GusBase+0x0A)!=0xAA) + return(false); + + // Program CODEC control register + MaxVal=((CodecBase & 0xF0)>>4) | 0x40; + if (Dma1 > 3) + MaxVal|=0x10; + if (Dma2 > 3) + MaxVal|=0x20; + dos_outportb(GusBase+0x106,MaxVal); + + CodecRegisterSelect=CodecBase; + CodecData=CodecBase+1; + CodecStatus=CodecBase+2; + + // Make sure there is a CODEC at the CODEC base + + // Clear any pending IRQs + dos_inportb(CodecStatus); + dos_outportb(CodecStatus,0); + + // Wait for 'INIT' bit to clear + for (i=0;i<0xFFFF;i++) + if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0) + break; + if (i==0xFFFF) + return(false); + + // Get chip revision - can not be zero + dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); + if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID) + return(false); + if ((dos_inportb(CodecData) & 0x0F) == 0) + return(false); + + HaveCodec=1; + Con_Printf("Sound Card is UltraSound MAX\n"); + return(true); +} + +//============================================================================= +// Get regular UltraSound configuration if any +//============================================================================= +static qboolean GUS_GetGUSData(void) +{ + char *Ultrasnd; + int GusBase,Dma1,Dma2,Irq1,Irq2,i; + + Ultrasnd=getenv("ULTRASND"); + if (Ultrasnd==NULL) + return(false); + + sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2); + + DmaChannel=Dma1 & 0x07; + + // Make sure there is a GUS at GUS base + dos_outportb(GusBase+0x08,0x55); + if (dos_inportb(GusBase+0x0A)!=0x55) + return(false); + dos_outportb(GusBase+0x08,0xAA); + if (dos_inportb(GusBase+0x0A)!=0xAA) + return(false); + + Gf1TimerControl = GusBase+0x008; + Gf1PageRegister = GusBase+0x102; + Gf1RegisterSelect = GusBase+0x103; + Gf1DataLow = GusBase+0x104; + Gf1DataHigh = GusBase+0x105; + + // Reset the GUS + SetGf18(MASTER_RESET,0x00); + Gf1Delay(); + Gf1Delay(); + SetGf18(MASTER_RESET,0x01); + Gf1Delay(); + Gf1Delay(); + + // Set to max (32) voices + SetGf18(SET_VOICES,0xDF); + + // Clear any pending IRQ's + ClearGf1Ints(); + + // Set all registers to known values + for (i=0;i<32;i++) + { + dos_outportb(Gf1PageRegister,i); + SetGf18(SET_CONTROL,0x03); + SetGf18(SET_VOLUME_CONTROL,0x03); + Gf1Delay(); + SetGf18(SET_CONTROL,0x03); + SetGf18(SET_VOLUME_CONTROL,0x03); + SetGf116(SET_START_HIGH,0); + SetGf116(SET_START_LOW,0); + SetGf116(SET_END_HIGH,0); + SetGf116(SET_END_LOW,0); + SetGf116(SET_ACC_HIGH,0); + SetGf116(SET_ACC_LOW,0); + SetGf18(SET_VOLUME_RATE,63); + SetGf18(SET_VOLUME_START,5); + SetGf18(SET_VOLUME_END,251); + SetGf116(SET_VOLUME,5<<8); + } + + // Clear any pending IRQ's + ClearGf1Ints(); + + // Enable DAC etc. + SetGf18(MASTER_RESET,0x07); + + // Enable line output so we can hear something + dos_outportb(GusBase,0x08); + + HaveCodec=0; + Con_Printf("Sound Card is UltraSound\n"); + return(true); +} + + +//============================================================================= +// Programs the DMA controller to start DMAing in Auto-init mode +//============================================================================= +static void GUS_StartDMA(BYTE DmaChannel,short *dma_buffer,int count) +{ + int mode; + int RealAddr; + + RealAddr = ptr2real(dma_buffer); + + if (DmaChannel <= 3) + { + ModeReg = 0x0B; + DisableReg = 0x0A; + ClearReg = 0x0E; + } + else + { + ModeReg = 0xD6; + DisableReg = 0xD4; + ClearReg = 0xDC; + } + CountReg=CountRegs[DmaChannel]; + AddrReg=AddrRegs[DmaChannel]; + + dos_outportb(DisableReg, DmaChannel | 4); // disable channel + + // set mode- see "undocumented pc", p.876 + mode = (1<<6) // single-cycle + +(0<<5) // address increment + +(1<<4) // auto-init dma + +(2<<2) // read + +(DmaChannel & 0x03); // channel # + dos_outportb(ModeReg, mode); + + // set page + dos_outportb(PageRegs[DmaChannel], RealAddr >> 16); + + if (DmaChannel <= 3) + { // address is in bytes + dos_outportb(0x0C, 0); // prepare to send 16-bit value + dos_outportb(AddrReg, RealAddr & 0xff); + dos_outportb(AddrReg, (RealAddr>>8) & 0xff); + + dos_outportb(0x0C, 0); // prepare to send 16-bit value + dos_outportb(CountReg, (count-1) & 0xff); + dos_outportb(CountReg, (count-1) >> 8); + } + else + { // address is in words + dos_outportb(0xD8, 0); // prepare to send 16-bit value + dos_outportb(AddrReg, (RealAddr>>1) & 0xff); + dos_outportb(AddrReg, (RealAddr>>9) & 0xff); + + dos_outportb(0xD8, 0); // prepare to send 16-bit value + dos_outportb(CountReg, ((count>>1)-1) & 0xff); + dos_outportb(CountReg, ((count>>1)-1) >> 8); + } + + dos_outportb(ClearReg, 0); // clear write mask + dos_outportb(DisableReg, DmaChannel & ~4); +} + +//============================================================================= +// Starts the CODEC playing +//============================================================================= +static void GUS_StartCODEC(int count,BYTE FSVal) +{ + int i,j; + + // Clear any pending IRQs + dos_inportb(CodecStatus); + dos_outportb(CodecStatus,0); + + // Set mode to 2 + dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID); + dos_outportb(CodecData,0xC0); + + // Stop any playback or capture which may be happening + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); + dos_outportb(CodecData,dos_inportb(CodecData) & 0xFC); + + // Set FS + dos_outportb(CodecRegisterSelect,CODEC_FS_FORMAT | 0x40); + dos_outportb(CodecData,FSVal | 0x50); // Or in stereo and 16 bit bits + + // Wait a bit + for (i=0;i<10;i++) + dos_inportb(CodecData); + + // Routine 1 to counter CODEC bug - wait for init bit to clear and then a + // bit longer (i=min loop count, j=timeout + for (i=0,j=0;i<1000 && j<0x7FFFF;j++) + if ((dos_inportb(CodecRegisterSelect) & 0x80)==0) + i++; + + // Routine 2 to counter CODEC bug - this is from Forte's code. For me it + // does not seem to cure the problem, but is added security + // Waits till we can modify index register + for (j=0;j<0x7FFFF;j++) + { + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); + if (dos_inportb(CodecRegisterSelect)==(CODEC_INTERFACE_CONFIG | 0x40)) + break; + } + + // Perform ACAL + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); + dos_outportb(CodecData,0x08); + + // Clear MCE bit - this makes ACAL happen + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); + + // Wait for ACAL to finish + for (j=0;j<0x7FFFF;j++) + { + if ((dos_inportb(CodecRegisterSelect) & 0x80) != 0) + continue; + dos_outportb(CodecRegisterSelect,CODEC_ERROR_STATUS_AND_INIT); + if ((dos_inportb(CodecData) & 0x20) == 0) + break; + } + + // Clear ACAL bit + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG | 0x40); + dos_outportb(CodecData,0x00); + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); + + // Set some other junk + dos_outportb(CodecRegisterSelect,CODEC_LOOPBACK_CONTROL); + dos_outportb(CodecData,0x00); + dos_outportb(CodecRegisterSelect,CODEC_PIN_CONTROL); + dos_outportb(CodecData,0x08); // IRQ is disabled in PIN control + + // Set count (it doesn't really matter what value we stuff in here + dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_LOWER_BASE_COUNT); + dos_outportb(CodecData,count & 0xFF); + dos_outportb(CodecRegisterSelect,CODEC_PLAYBACK_UPPER_BASE_COUNT); + dos_outportb(CodecData,count >> 8); + + // Start playback + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); + dos_outportb(CodecData,0x01); +} + +//============================================================================= +// Starts the GF1 playing +//============================================================================= +static void GUS_StartGf1(int count,BYTE Voices) +{ + DWORD StartAddressL,EndAddressL,StartAddressR,EndAddressR; + + // Set number of voices to give us the sampling rate we want + SetGf18(SET_VOICES,0xC0 | (Voices-1)); + + // Figure out addresses + StartAddressL=ConvertTo16(0); + EndAddressL=ConvertTo16(count-2-2); + StartAddressR=ConvertTo16(2); + EndAddressR=ConvertTo16(count-2); + + // Set left voice addresses + dos_outportb(Gf1PageRegister,0); + SetGf116(SET_START_LOW,StartAddressL<<9); + SetGf116(SET_START_HIGH,StartAddressL>>7); + SetGf116(SET_ACC_LOW,StartAddressL<<9); + SetGf116(SET_ACC_HIGH,StartAddressL>>7); + SetGf116(SET_END_LOW,EndAddressL<<9); + SetGf116(SET_END_HIGH,EndAddressL>>7); + // Set balance to full left + SetGf18(SET_BALANCE,0); + // Set volume to full + SetGf116(SET_VOLUME,0xFFF0); + // Set FC to 2 (so we play every second sample) + SetGf116(SET_FREQUENCY,0x0800); + + // Set right voice addresses + dos_outportb(Gf1PageRegister,1); + SetGf116(SET_START_LOW,StartAddressR<<9); + SetGf116(SET_START_HIGH,StartAddressR>>7); + SetGf116(SET_ACC_LOW,StartAddressR<<9); + SetGf116(SET_ACC_HIGH,StartAddressR>>7); + SetGf116(SET_END_LOW,EndAddressR<<9); + SetGf116(SET_END_HIGH,EndAddressR>>7); + // Set balance to full right + SetGf18(SET_BALANCE,15); + // Set volume to full + SetGf116(SET_VOLUME,0xFFF0); + // Set FC to 2 (so we play every second sample) + SetGf116(SET_FREQUENCY,0x0800); + + // Start voices + dos_outportb(Gf1PageRegister,0); + SetGf18(SET_CONTROL,0x0C); + dos_outportb(Gf1PageRegister,1); + SetGf18(SET_CONTROL,0x0C); + Gf1Delay(); + dos_outportb(Gf1PageRegister,0); + SetGf18(SET_CONTROL,0x0C); + dos_outportb(Gf1PageRegister,1); + SetGf18(SET_CONTROL,0x0C); +} + + +//============================================================================= +// Figures out what kind of UltraSound we have, if any, and starts it playing +//============================================================================= +qboolean GUS_Init(void) +{ + int rc; + int RealAddr; + BYTE FSVal,Voices; + struct CodecRateStruct *CodecRate; + struct Gf1RateStruct *Gf1Rate; + + // See what kind of UltraSound we have, if any + if (GUS_GetIWData()==false) + if (GUS_GetMAXData()==false) + if (GUS_GetGUSData()==false) + return(false); + + shm = &sn; + + if (HaveCodec) + { + // do 11khz sampling rate unless command line parameter wants different + shm->speed = 11025; + FSVal = 0x03; + rc = COM_CheckParm("-sspeed"); + if (rc) + { + shm->speed = Q_atoi(com_argv[rc+1]); + + // Make sure rate not too high + if (shm->speed>48000) + shm->speed=48000; + + // Adjust speed to match one of the possible CODEC rates + for (CodecRate=CodecRates;CodecRate->Rate!=0;CodecRate++) + { + if (shm->speed <= CodecRate->Rate) + { + shm->speed=CodecRate->Rate; + FSVal=CodecRate->FSVal; + break; + } + } + } + + + // Always do 16 bit stereo + shm->channels = 2; + shm->samplebits = 16; + + // allocate buffer twice the size we need so we can get aligned buffer + dma_buffer = dos_getmemory(BUFFER_SIZE*2); + if (dma_buffer==NULL) + { + Con_Printf("Couldn't allocate sound dma buffer"); + return false; + } + + RealAddr = ptr2real(dma_buffer); + RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1); + dma_buffer = (short *) real2ptr(RealAddr); + + // Zero off DMA buffer + memset(dma_buffer, 0, BUFFER_SIZE); + + shm->soundalive = true; + shm->splitbuffer = false; + + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) dma_buffer; + shm->samples = BUFFER_SIZE/(shm->samplebits/8); + + GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); + GUS_StartCODEC(BUFFER_SIZE,FSVal); + } + else + { + // do 19khz sampling rate unless command line parameter wants different + shm->speed = 19293; + Voices=32; + rc = COM_CheckParm("-sspeed"); + if (rc) + { + shm->speed = Q_atoi(com_argv[rc+1]); + + // Make sure rate not too high + if (shm->speed>44100) + shm->speed=44100; + + // Adjust speed to match one of the possible GF1 rates + for (Gf1Rate=Gf1Rates;Gf1Rate->Rate!=0;Gf1Rate++) + { + if (shm->speed <= Gf1Rate->Rate) + { + shm->speed=Gf1Rate->Rate; + Voices=Gf1Rate->Voices; + break; + } + } + } + + // Always do 16 bit stereo + shm->channels = 2; + shm->samplebits = 16; + + // allocate buffer twice the size we need so we can get aligned buffer + dma_buffer = dos_getmemory(BUFFER_SIZE*2); + if (dma_buffer==NULL) + { + Con_Printf("Couldn't allocate sound dma buffer"); + return false; + } + + RealAddr = ptr2real(dma_buffer); + RealAddr = (RealAddr + BUFFER_SIZE) & ~(BUFFER_SIZE-1); + dma_buffer = (short *) real2ptr(RealAddr); + + // Zero off DMA buffer + memset(dma_buffer, 0, BUFFER_SIZE); + + shm->soundalive = true; + shm->splitbuffer = false; + + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) dma_buffer; + shm->samples = BUFFER_SIZE/(shm->samplebits/8); + + GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); + SetGf116(SET_DMA_ADDRESS,0x0000); + if (DmaChannel<=3) + SetGf18(DMA_CONTROL,0x41); + else + SetGf18(DMA_CONTROL,0x45); + GUS_StartGf1(BUFFER_SIZE,Voices); + } + return(true); +} + +//============================================================================= +// Returns the current playback position +//============================================================================= +int GUS_GetDMAPos(void) +{ + int count; + + if (HaveCodec) + { + // clear 16-bit reg flip-flop + // load the current dma count register + if (DmaChannel < 4) + { + dos_outportb(0x0C, 0); + count = dos_inportb(CountReg); + count += dos_inportb(CountReg) << 8; + if (shm->samplebits == 16) + count /= 2; + count = shm->samples - (count+1); + } + else + { + dos_outportb(0xD8, 0); + count = dos_inportb(CountReg); + count += dos_inportb(CountReg) << 8; + if (shm->samplebits == 8) + count *= 2; + count = shm->samples - (count+1); + } + + } + else + { + // Read current position from GF1 + dos_outportb(Gf1PageRegister,0); + count=(GetGf116(GET_ACC_HIGH)<<7) & 0xFFFF; + // See which half of buffer we are in. Note that since this is 16 bit + // data we are playing, position is in 16 bit samples + if (GetGf18(DMA_CONTROL) & 0x40) + { + GUS_StartDMA(DmaChannel,dma_buffer,BUFFER_SIZE); + SetGf116(SET_DMA_ADDRESS,0x0000); + if (DmaChannel<=3) + SetGf18(DMA_CONTROL,0x41); + else + SetGf18(DMA_CONTROL,0x45); + } + } + + shm->samplepos = count & (shm->samples-1); + return(shm->samplepos); +} + +//============================================================================= +// Stops the UltraSound playback +//============================================================================= +void GUS_Shutdown (void) +{ + if (HaveCodec) + { + // Stop CODEC + dos_outportb(CodecRegisterSelect,CODEC_INTERFACE_CONFIG); + dos_outportb(CodecData,0x01); + } + else + { + // Stop Voices + dos_outportb(Gf1PageRegister,0); + SetGf18(SET_CONTROL,0x03); + dos_outportb(Gf1PageRegister,1); + SetGf18(SET_CONTROL,0x03); + Gf1Delay(); + dos_outportb(Gf1PageRegister,0); + SetGf18(SET_CONTROL,0x03); + dos_outportb(Gf1PageRegister,1); + SetGf18(SET_CONTROL,0x03); + + // Stop any DMA + SetGf18(DMA_CONTROL,0x00); + GetGf18(DMA_CONTROL); + } + + dos_outportb(DisableReg, DmaChannel | 4); // disable dma channel +} diff --git a/WinQuake/snd_linux.c b/WinQuake/snd_linux.c index 4579e40..bcaf8e9 100644 --- a/WinQuake/snd_linux.c +++ b/WinQuake/snd_linux.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #include #include #include diff --git a/WinQuake/snd_mem.c b/WinQuake/snd_mem.c index 71e32aa..494928a 100644 --- a/WinQuake/snd_mem.c +++ b/WinQuake/snd_mem.c @@ -1,341 +1,341 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// snd_mem.c: sound caching - -#include "quakedef.h" - -int cache_full_cycle; - -byte *S_Alloc (int size); - -/* -================ -ResampleSfx -================ -*/ -void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) -{ - int outcount; - int srcsample; - float stepscale; - int i; - int sample, samplefrac, fracstep; - sfxcache_t *sc; - - sc = Cache_Check (&sfx->cache); - if (!sc) - return; - - stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 - - outcount = sc->length / stepscale; - sc->length = outcount; - if (sc->loopstart != -1) - sc->loopstart = sc->loopstart / stepscale; - - sc->speed = shm->speed; - if (loadas8bit.value) - sc->width = 1; - else - sc->width = inwidth; - sc->stereo = 0; - -// resample / decimate to the current source rate - - if (stepscale == 1 && inwidth == 1 && sc->width == 1) - { -// fast special case - for (i=0 ; idata)[i] - = (int)( (unsigned char)(data[i]) - 128); - } - else - { -// general case - samplefrac = 0; - fracstep = stepscale*256; - for (i=0 ; i> 8; - samplefrac += fracstep; - if (inwidth == 2) - sample = LittleShort ( ((short *)data)[srcsample] ); - else - sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; - if (sc->width == 2) - ((short *)sc->data)[i] = sample; - else - ((signed char *)sc->data)[i] = sample >> 8; - } - } -} - -//============================================================================= - -/* -============== -S_LoadSound -============== -*/ -sfxcache_t *S_LoadSound (sfx_t *s) -{ - char namebuffer[256]; - byte *data; - wavinfo_t info; - int len; - float stepscale; - sfxcache_t *sc; - byte stackbuf[1*1024]; // avoid dirtying the cache heap - -// see if still in memory - sc = Cache_Check (&s->cache); - if (sc) - return sc; - -//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); -// load it in - Q_strcpy(namebuffer, "sound/"); - Q_strcat(namebuffer, s->name); - -// Con_Printf ("loading %s\n",namebuffer); - - data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); - - if (!data) - { - Con_Printf ("Couldn't load %s\n", namebuffer); - return NULL; - } - - info = GetWavinfo (s->name, data, com_filesize); - if (info.channels != 1) - { - Con_Printf ("%s is a stereo sample\n",s->name); - return NULL; - } - - stepscale = (float)info.rate / shm->speed; - len = info.samples / stepscale; - - len = len * info.width * info.channels; - - sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); - if (!sc) - return NULL; - - sc->length = info.samples; - sc->loopstart = info.loopstart; - sc->speed = info.rate; - sc->width = info.width; - sc->stereo = info.channels; - - ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); - - return sc; -} - - - -/* -=============================================================================== - -WAV loading - -=============================================================================== -*/ - - -byte *data_p; -byte *iff_end; -byte *last_chunk; -byte *iff_data; -int iff_chunk_len; - - -short GetLittleShort(void) -{ - short val = 0; - val = *data_p; - val = val + (*(data_p+1)<<8); - data_p += 2; - return val; -} - -int GetLittleLong(void) -{ - int val = 0; - val = *data_p; - val = val + (*(data_p+1)<<8); - val = val + (*(data_p+2)<<16); - val = val + (*(data_p+3)<<24); - data_p += 4; - return val; -} - -void FindNextChunk(char *name) -{ - while (1) - { - data_p=last_chunk; - - if (data_p >= iff_end) - { // didn't find the chunk - data_p = NULL; - return; - } - - data_p += 4; - iff_chunk_len = GetLittleLong(); - if (iff_chunk_len < 0) - { - data_p = NULL; - return; - } -// if (iff_chunk_len > 1024*1024) -// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); - data_p -= 8; - last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); - if (!Q_strncmp(data_p, name, 4)) - return; - } -} - -void FindChunk(char *name) -{ - last_chunk = iff_data; - FindNextChunk (name); -} - - -void DumpChunks(void) -{ - char str[5]; - - str[4] = 0; - data_p=iff_data; - do - { - memcpy (str, data_p, 4); - data_p += 4; - iff_chunk_len = GetLittleLong(); - Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); - data_p += (iff_chunk_len + 1) & ~1; - } while (data_p < iff_end); -} - -/* -============ -GetWavinfo -============ -*/ -wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) -{ - wavinfo_t info; - int i; - int format; - int samples; - - memset (&info, 0, sizeof(info)); - - if (!wav) - return info; - - iff_data = wav; - iff_end = wav + wavlength; - -// find "RIFF" chunk - FindChunk("RIFF"); - if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) - { - Con_Printf("Missing RIFF/WAVE chunks\n"); - return info; - } - -// get "fmt " chunk - iff_data = data_p + 12; -// DumpChunks (); - - FindChunk("fmt "); - if (!data_p) - { - Con_Printf("Missing fmt chunk\n"); - return info; - } - data_p += 8; - format = GetLittleShort(); - if (format != 1) - { - Con_Printf("Microsoft PCM format only\n"); - return info; - } - - info.channels = GetLittleShort(); - info.rate = GetLittleLong(); - data_p += 4+2; - info.width = GetLittleShort() / 8; - -// get cue chunk - FindChunk("cue "); - if (data_p) - { - data_p += 32; - info.loopstart = GetLittleLong(); -// Con_Printf("loopstart=%d\n", sfx->loopstart); - - // if the next chunk is a LIST chunk, look for a cue length marker - FindNextChunk ("LIST"); - if (data_p) - { - if (!strncmp (data_p + 28, "mark", 4)) - { // this is not a proper parse, but it works with cooledit... - data_p += 24; - i = GetLittleLong (); // samples in loop - info.samples = info.loopstart + i; -// Con_Printf("looped length: %i\n", i); - } - } - } - else - info.loopstart = -1; - -// find data chunk - FindChunk("data"); - if (!data_p) - { - Con_Printf("Missing data chunk\n"); - return info; - } - - data_p += 4; - samples = GetLittleLong () / info.width; - - if (info.samples) - { - if (samples < info.samples) - Sys_Error ("Sound %s has a bad loop length", name); - } - else - info.samples = samples; - - info.dataofs = data_p - wav; - - return info; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// snd_mem.c: sound caching + +#include "quakedef.h" + +int cache_full_cycle; + +byte *S_Alloc (int size); + +/* +================ +ResampleSfx +================ +*/ +void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) +{ + int outcount; + int srcsample; + float stepscale; + int i; + int sample, samplefrac, fracstep; + sfxcache_t *sc; + + sc = Cache_Check (&sfx->cache); + if (!sc) + return; + + stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 + + outcount = sc->length / stepscale; + sc->length = outcount; + if (sc->loopstart != -1) + sc->loopstart = sc->loopstart / stepscale; + + sc->speed = shm->speed; + if (loadas8bit.value) + sc->width = 1; + else + sc->width = inwidth; + sc->stereo = 0; + +// resample / decimate to the current source rate + + if (stepscale == 1 && inwidth == 1 && sc->width == 1) + { +// fast special case + for (i=0 ; idata)[i] + = (int)( (unsigned char)(data[i]) - 128); + } + else + { +// general case + samplefrac = 0; + fracstep = stepscale*256; + for (i=0 ; i> 8; + samplefrac += fracstep; + if (inwidth == 2) + sample = LittleShort ( ((short *)data)[srcsample] ); + else + sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; + if (sc->width == 2) + ((short *)sc->data)[i] = sample; + else + ((signed char *)sc->data)[i] = sample >> 8; + } + } +} + +//============================================================================= + +/* +============== +S_LoadSound +============== +*/ +sfxcache_t *S_LoadSound (sfx_t *s) +{ + char namebuffer[256]; + byte *data; + wavinfo_t info; + int len; + float stepscale; + sfxcache_t *sc; + byte stackbuf[1*1024]; // avoid dirtying the cache heap + +// see if still in memory + sc = Cache_Check (&s->cache); + if (sc) + return sc; + +//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); +// load it in + Q_strcpy(namebuffer, "sound/"); + Q_strcat(namebuffer, s->name); + +// Con_Printf ("loading %s\n",namebuffer); + + data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); + + if (!data) + { + Con_Printf ("Couldn't load %s\n", namebuffer); + return NULL; + } + + info = GetWavinfo (s->name, data, com_filesize); + if (info.channels != 1) + { + Con_Printf ("%s is a stereo sample\n",s->name); + return NULL; + } + + stepscale = (float)info.rate / shm->speed; + len = info.samples / stepscale; + + len = len * info.width * info.channels; + + sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); + if (!sc) + return NULL; + + sc->length = info.samples; + sc->loopstart = info.loopstart; + sc->speed = info.rate; + sc->width = info.width; + sc->stereo = info.channels; + + ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); + + return sc; +} + + + +/* +=============================================================================== + +WAV loading + +=============================================================================== +*/ + + +byte *data_p; +byte *iff_end; +byte *last_chunk; +byte *iff_data; +int iff_chunk_len; + + +short GetLittleShort(void) +{ + short val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + data_p += 2; + return val; +} + +int GetLittleLong(void) +{ + int val = 0; + val = *data_p; + val = val + (*(data_p+1)<<8); + val = val + (*(data_p+2)<<16); + val = val + (*(data_p+3)<<24); + data_p += 4; + return val; +} + +void FindNextChunk(char *name) +{ + while (1) + { + data_p=last_chunk; + + if (data_p >= iff_end) + { // didn't find the chunk + data_p = NULL; + return; + } + + data_p += 4; + iff_chunk_len = GetLittleLong(); + if (iff_chunk_len < 0) + { + data_p = NULL; + return; + } +// if (iff_chunk_len > 1024*1024) +// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); + data_p -= 8; + last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); + if (!Q_strncmp(data_p, name, 4)) + return; + } +} + +void FindChunk(char *name) +{ + last_chunk = iff_data; + FindNextChunk (name); +} + + +void DumpChunks(void) +{ + char str[5]; + + str[4] = 0; + data_p=iff_data; + do + { + memcpy (str, data_p, 4); + data_p += 4; + iff_chunk_len = GetLittleLong(); + Con_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); + data_p += (iff_chunk_len + 1) & ~1; + } while (data_p < iff_end); +} + +/* +============ +GetWavinfo +============ +*/ +wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) +{ + wavinfo_t info; + int i; + int format; + int samples; + + memset (&info, 0, sizeof(info)); + + if (!wav) + return info; + + iff_data = wav; + iff_end = wav + wavlength; + +// find "RIFF" chunk + FindChunk("RIFF"); + if (!(data_p && !Q_strncmp(data_p+8, "WAVE", 4))) + { + Con_Printf("Missing RIFF/WAVE chunks\n"); + return info; + } + +// get "fmt " chunk + iff_data = data_p + 12; +// DumpChunks (); + + FindChunk("fmt "); + if (!data_p) + { + Con_Printf("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) + { + Con_Printf("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4+2; + info.width = GetLittleShort() / 8; + +// get cue chunk + FindChunk("cue "); + if (data_p) + { + data_p += 32; + info.loopstart = GetLittleLong(); +// Con_Printf("loopstart=%d\n", sfx->loopstart); + + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk ("LIST"); + if (data_p) + { + if (!strncmp (data_p + 28, "mark", 4)) + { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong (); // samples in loop + info.samples = info.loopstart + i; +// Con_Printf("looped length: %i\n", i); + } + } + } + else + info.loopstart = -1; + +// find data chunk + FindChunk("data"); + if (!data_p) + { + Con_Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong () / info.width; + + if (info.samples) + { + if (samples < info.samples) + Sys_Error ("Sound %s has a bad loop length", name); + } + else + info.samples = samples; + + info.dataofs = data_p - wav; + + return info; +} + diff --git a/WinQuake/snd_mix.c b/WinQuake/snd_mix.c index d31f6c9..c040494 100644 --- a/WinQuake/snd_mix.c +++ b/WinQuake/snd_mix.c @@ -1,398 +1,398 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// snd_mix.c -- portable code to mix sounds for snd_dma.c - -#include "quakedef.h" - -#ifdef _WIN32 -#include "winquake.h" -#else -#define DWORD unsigned long -#endif - -#define PAINTBUFFER_SIZE 512 -portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; -int snd_scaletable[32][256]; -int *snd_p, snd_linear_count, snd_vol; -short *snd_out; - -void Snd_WriteLinearBlastStereo16 (void); - -#if !id386 -void Snd_WriteLinearBlastStereo16 (void) -{ - int i; - int val; - - for (i=0 ; i>8; - if (val > 0x7fff) - snd_out[i] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i] = (short)0x8000; - else - snd_out[i] = val; - - val = (snd_p[i+1]*snd_vol)>>8; - if (val > 0x7fff) - snd_out[i+1] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i+1] = (short)0x8000; - else - snd_out[i+1] = val; - } -} -#endif - -void S_TransferStereo16 (int endtime) -{ - int lpos; - int lpaintedtime; - DWORD *pbuf; -#ifdef _WIN32 - int reps; - DWORD dwSize,dwSize2; - DWORD *pbuf2; - HRESULT hresult; -#endif - - snd_vol = volume.value*256; - - snd_p = (int *) paintbuffer; - lpaintedtime = paintedtime; - -#ifdef _WIN32 - if (pDSBuf) - { - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2, &dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - S_Startup (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - S_Shutdown (); - S_Startup (); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)shm->buffer; - } - - while (lpaintedtime < endtime) - { - // handle recirculating buffer issues - lpos = lpaintedtime & ((shm->samples>>1)-1); - - snd_out = (short *) pbuf + (lpos<<1); - - snd_linear_count = (shm->samples>>1) - lpos; - if (lpaintedtime + snd_linear_count > endtime) - snd_linear_count = endtime - lpaintedtime; - - snd_linear_count <<= 1; - - // write a linear blast of samples - Snd_WriteLinearBlastStereo16 (); - - snd_p += snd_linear_count; - lpaintedtime += (snd_linear_count>>1); - } - -#ifdef _WIN32 - if (pDSBuf) - pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); -#endif -} - -void S_TransferPaintBuffer(int endtime) -{ - int out_idx; - int count; - int out_mask; - int *p; - int step; - int val; - int snd_vol; - DWORD *pbuf; -#ifdef _WIN32 - int reps; - DWORD dwSize,dwSize2; - DWORD *pbuf2; - HRESULT hresult; -#endif - - if (shm->samplebits == 16 && shm->channels == 2) - { - S_TransferStereo16 (endtime); - return; - } - - p = (int *) paintbuffer; - count = (endtime - paintedtime) * shm->channels; - out_mask = shm->samples - 1; - out_idx = paintedtime * shm->channels & out_mask; - step = 3 - shm->channels; - snd_vol = volume.value*256; - -#ifdef _WIN32 - if (pDSBuf) - { - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2,&dwSize2, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); - S_Shutdown (); - S_Startup (); - return; - } - - if (++reps > 10000) - { - Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); - S_Shutdown (); - S_Startup (); - return; - } - } - } - else -#endif - { - pbuf = (DWORD *)shm->buffer; - } - - if (shm->samplebits == 16) - { - short *out = (short *) pbuf; - while (count--) - { - val = (*p * snd_vol) >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = val; - out_idx = (out_idx + 1) & out_mask; - } - } - else if (shm->samplebits == 8) - { - unsigned char *out = (unsigned char *) pbuf; - while (count--) - { - val = (*p * snd_vol) >> 8; - p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = (val>>8) + 128; - out_idx = (out_idx + 1) & out_mask; - } - } - -#ifdef _WIN32 - if (pDSBuf) { - DWORD dwNewpos, dwWrite; - int il = paintedtime; - int ir = endtime - paintedtime; - - ir += il; - - pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); - - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite); - -// if ((dwNewpos >= il) && (dwNewpos <= ir)) -// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); - } -#endif -} - - -/* -=============================================================================== - -CHANNEL MIXING - -=============================================================================== -*/ - -void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime); -void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime); - -void S_PaintChannels(int endtime) -{ - int i; - int end; - channel_t *ch; - sfxcache_t *sc; - int ltime, count; - - while (paintedtime < endtime) - { - // if paintbuffer is smaller than DMA buffer - end = endtime; - if (endtime - paintedtime > PAINTBUFFER_SIZE) - end = paintedtime + PAINTBUFFER_SIZE; - - // clear the paint buffer - Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); - - // paint in the channels. - ch = channels; - for (i=0; isfx) - continue; - if (!ch->leftvol && !ch->rightvol) - continue; - sc = S_LoadSound (ch->sfx); - if (!sc) - continue; - - ltime = paintedtime; - - while (ltime < end) - { // paint up to end - if (ch->end < end) - count = ch->end - ltime; - else - count = end - ltime; - - if (count > 0) - { - if (sc->width == 1) - SND_PaintChannelFrom8(ch, sc, count); - else - SND_PaintChannelFrom16(ch, sc, count); - - ltime += count; - } - - // if at end of loop, restart - if (ltime >= ch->end) - { - if (sc->loopstart >= 0) - { - ch->pos = sc->loopstart; - ch->end = ltime + sc->length - ch->pos; - } - else - { // channel just stopped - ch->sfx = NULL; - break; - } - } - } - - } - - // transfer out according to DMA format - S_TransferPaintBuffer(end); - paintedtime = end; - } -} - -void SND_InitScaletable (void) -{ - int i, j; - - for (i=0 ; i<32 ; i++) - for (j=0 ; j<256 ; j++) - snd_scaletable[i][j] = ((signed char)j) * i * 8; -} - - -#if !id386 - -void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) -{ - int data; - int *lscale, *rscale; - unsigned char *sfx; - int i; - - if (ch->leftvol > 255) - ch->leftvol = 255; - if (ch->rightvol > 255) - ch->rightvol = 255; - - lscale = snd_scaletable[ch->leftvol >> 3]; - rscale = snd_scaletable[ch->rightvol >> 3]; - sfx = (signed char *)sc->data + ch->pos; - - for (i=0 ; ipos += count; -} - -#endif // !id386 - - -void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) -{ - int data; - int left, right; - int leftvol, rightvol; - signed short *sfx; - int i; - - leftvol = ch->leftvol; - rightvol = ch->rightvol; - sfx = (signed short *)sc->data + ch->pos; - - for (i=0 ; i> 8; - right = (data * rightvol) >> 8; - paintbuffer[i].left += left; - paintbuffer[i].right += right; - } - - ch->pos += count; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// snd_mix.c -- portable code to mix sounds for snd_dma.c + +#include "quakedef.h" + +#ifdef _WIN32 +#include "winquake.h" +#else +#define DWORD unsigned long +#endif + +#define PAINTBUFFER_SIZE 512 +portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; +int snd_scaletable[32][256]; +int *snd_p, snd_linear_count, snd_vol; +short *snd_out; + +void Snd_WriteLinearBlastStereo16 (void); + +#if !id386 +void Snd_WriteLinearBlastStereo16 (void) +{ + int i; + int val; + + for (i=0 ; i>8; + if (val > 0x7fff) + snd_out[i] = 0x7fff; + else if (val < (short)0x8000) + snd_out[i] = (short)0x8000; + else + snd_out[i] = val; + + val = (snd_p[i+1]*snd_vol)>>8; + if (val > 0x7fff) + snd_out[i+1] = 0x7fff; + else if (val < (short)0x8000) + snd_out[i+1] = (short)0x8000; + else + snd_out[i+1] = val; + } +} +#endif + +void S_TransferStereo16 (int endtime) +{ + int lpos; + int lpaintedtime; + DWORD *pbuf; +#ifdef _WIN32 + int reps; + DWORD dwSize,dwSize2; + DWORD *pbuf2; + HRESULT hresult; +#endif + + snd_vol = volume.value*256; + + snd_p = (int *) paintbuffer; + lpaintedtime = paintedtime; + +#ifdef _WIN32 + if (pDSBuf) + { + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, + &pbuf2, &dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + S_Startup (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); + S_Shutdown (); + S_Startup (); + return; + } + } + } + else +#endif + { + pbuf = (DWORD *)shm->buffer; + } + + while (lpaintedtime < endtime) + { + // handle recirculating buffer issues + lpos = lpaintedtime & ((shm->samples>>1)-1); + + snd_out = (short *) pbuf + (lpos<<1); + + snd_linear_count = (shm->samples>>1) - lpos; + if (lpaintedtime + snd_linear_count > endtime) + snd_linear_count = endtime - lpaintedtime; + + snd_linear_count <<= 1; + + // write a linear blast of samples + Snd_WriteLinearBlastStereo16 (); + + snd_p += snd_linear_count; + lpaintedtime += (snd_linear_count>>1); + } + +#ifdef _WIN32 + if (pDSBuf) + pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); +#endif +} + +void S_TransferPaintBuffer(int endtime) +{ + int out_idx; + int count; + int out_mask; + int *p; + int step; + int val; + int snd_vol; + DWORD *pbuf; +#ifdef _WIN32 + int reps; + DWORD dwSize,dwSize2; + DWORD *pbuf2; + HRESULT hresult; +#endif + + if (shm->samplebits == 16 && shm->channels == 2) + { + S_TransferStereo16 (endtime); + return; + } + + p = (int *) paintbuffer; + count = (endtime - paintedtime) * shm->channels; + out_mask = shm->samples - 1; + out_idx = paintedtime * shm->channels & out_mask; + step = 3 - shm->channels; + snd_vol = volume.value*256; + +#ifdef _WIN32 + if (pDSBuf) + { + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, + &pbuf2,&dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n"); + S_Shutdown (); + S_Startup (); + return; + } + + if (++reps > 10000) + { + Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n"); + S_Shutdown (); + S_Startup (); + return; + } + } + } + else +#endif + { + pbuf = (DWORD *)shm->buffer; + } + + if (shm->samplebits == 16) + { + short *out = (short *) pbuf; + while (count--) + { + val = (*p * snd_vol) >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = val; + out_idx = (out_idx + 1) & out_mask; + } + } + else if (shm->samplebits == 8) + { + unsigned char *out = (unsigned char *) pbuf; + while (count--) + { + val = (*p * snd_vol) >> 8; + p+= step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < (short)0x8000) + val = (short)0x8000; + out[out_idx] = (val>>8) + 128; + out_idx = (out_idx + 1) & out_mask; + } + } + +#ifdef _WIN32 + if (pDSBuf) { + DWORD dwNewpos, dwWrite; + int il = paintedtime; + int ir = endtime - paintedtime; + + ir += il; + + pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0); + + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite); + +// if ((dwNewpos >= il) && (dwNewpos <= ir)) +// Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos); + } +#endif +} + + +/* +=============================================================================== + +CHANNEL MIXING + +=============================================================================== +*/ + +void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime); +void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime); + +void S_PaintChannels(int endtime) +{ + int i; + int end; + channel_t *ch; + sfxcache_t *sc; + int ltime, count; + + while (paintedtime < endtime) + { + // if paintbuffer is smaller than DMA buffer + end = endtime; + if (endtime - paintedtime > PAINTBUFFER_SIZE) + end = paintedtime + PAINTBUFFER_SIZE; + + // clear the paint buffer + Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); + + // paint in the channels. + ch = channels; + for (i=0; isfx) + continue; + if (!ch->leftvol && !ch->rightvol) + continue; + sc = S_LoadSound (ch->sfx); + if (!sc) + continue; + + ltime = paintedtime; + + while (ltime < end) + { // paint up to end + if (ch->end < end) + count = ch->end - ltime; + else + count = end - ltime; + + if (count > 0) + { + if (sc->width == 1) + SND_PaintChannelFrom8(ch, sc, count); + else + SND_PaintChannelFrom16(ch, sc, count); + + ltime += count; + } + + // if at end of loop, restart + if (ltime >= ch->end) + { + if (sc->loopstart >= 0) + { + ch->pos = sc->loopstart; + ch->end = ltime + sc->length - ch->pos; + } + else + { // channel just stopped + ch->sfx = NULL; + break; + } + } + } + + } + + // transfer out according to DMA format + S_TransferPaintBuffer(end); + paintedtime = end; + } +} + +void SND_InitScaletable (void) +{ + int i, j; + + for (i=0 ; i<32 ; i++) + for (j=0 ; j<256 ; j++) + snd_scaletable[i][j] = ((signed char)j) * i * 8; +} + + +#if !id386 + +void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) +{ + int data; + int *lscale, *rscale; + unsigned char *sfx; + int i; + + if (ch->leftvol > 255) + ch->leftvol = 255; + if (ch->rightvol > 255) + ch->rightvol = 255; + + lscale = snd_scaletable[ch->leftvol >> 3]; + rscale = snd_scaletable[ch->rightvol >> 3]; + sfx = (signed char *)sc->data + ch->pos; + + for (i=0 ; ipos += count; +} + +#endif // !id386 + + +void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) +{ + int data; + int left, right; + int leftvol, rightvol; + signed short *sfx; + int i; + + leftvol = ch->leftvol; + rightvol = ch->rightvol; + sfx = (signed short *)sc->data + ch->pos; + + for (i=0 ; i> 8; + right = (data * rightvol) >> 8; + paintbuffer[i].left += left; + paintbuffer[i].right += right; + } + + ch->pos += count; +} + diff --git a/WinQuake/snd_mixa.s b/WinQuake/snd_mixa.s index 7fa190b..6abb8a5 100644 --- a/WinQuake/snd_mixa.s +++ b/WinQuake/snd_mixa.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // snd_mixa.s // x86 assembly-language sound code diff --git a/WinQuake/snd_next.c b/WinQuake/snd_next.c index e732da3..9e66f2b 100644 --- a/WinQuake/snd_next.c +++ b/WinQuake/snd_next.c @@ -1,55 +1,55 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - -extern int desired_speed; -extern int desired_bits; - -qboolean SNDDMA_Init(void) -{ - int size; - - size = 16384 + sizeof(dma_t); - shm = malloc (size); - memset((void*)shm, 0, size); - - shm->buffer = (char*)shm + sizeof(dma_t); - shm->channels = 2; - shm->speed = desired_speed; - shm->samplebits = desired_bits; - shm->samples = 16384 / (desired_bits / 8); - shm->submission_chunk = 1; - - return true; -} - -// return the current sample position (in mono samples read) -// inside the recirculating dma buffer -int SNDDMA_GetDMAPos(void) -{ - shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1); - - return shm->samplepos; -} - -void SNDDMA_Shutdown(void) -{ -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +extern int desired_speed; +extern int desired_bits; + +qboolean SNDDMA_Init(void) +{ + int size; + + size = 16384 + sizeof(dma_t); + shm = malloc (size); + memset((void*)shm, 0, size); + + shm->buffer = (char*)shm + sizeof(dma_t); + shm->channels = 2; + shm->speed = desired_speed; + shm->samplebits = desired_bits; + shm->samples = 16384 / (desired_bits / 8); + shm->submission_chunk = 1; + + return true; +} + +// return the current sample position (in mono samples read) +// inside the recirculating dma buffer +int SNDDMA_GetDMAPos(void) +{ + shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1); + + return shm->samplepos; +} + +void SNDDMA_Shutdown(void) +{ +} diff --git a/WinQuake/snd_null.c b/WinQuake/snd_null.c index 9db2ebc..6dea5cf 100644 --- a/WinQuake/snd_null.c +++ b/WinQuake/snd_null.c @@ -1,97 +1,97 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// snd_null.c -- include this instead of all the other snd_* files to have -// no sound code whatsoever - -#include "quakedef.h" - -cvar_t bgmvolume = {"bgmvolume", "1", true}; -cvar_t volume = {"volume", "0.7", true}; - - -void S_Init (void) -{ -} - -void S_AmbientOff (void) -{ -} - -void S_AmbientOn (void) -{ -} - -void S_Shutdown (void) -{ -} - -void S_TouchSound (char *sample) -{ -} - -void S_ClearBuffer (void) -{ -} - -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) -{ -} - -void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) -{ -} - -void S_StopSound (int entnum, int entchannel) -{ -} - -sfx_t *S_PrecacheSound (char *sample) -{ - return NULL; -} - -void S_ClearPrecache (void) -{ -} - -void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up) -{ -} - -void S_StopAllSounds (qboolean clear) -{ -} - -void S_BeginPrecaching (void) -{ -} - -void S_EndPrecaching (void) -{ -} - -void S_ExtraUpdate (void) -{ -} - -void S_LocalSound (char *s) -{ -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// snd_null.c -- include this instead of all the other snd_* files to have +// no sound code whatsoever + +#include "quakedef.h" + +cvar_t bgmvolume = {"bgmvolume", "1", true}; +cvar_t volume = {"volume", "0.7", true}; + + +void S_Init (void) +{ +} + +void S_AmbientOff (void) +{ +} + +void S_AmbientOn (void) +{ +} + +void S_Shutdown (void) +{ +} + +void S_TouchSound (char *sample) +{ +} + +void S_ClearBuffer (void) +{ +} + +void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) +{ +} + +void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +{ +} + +void S_StopSound (int entnum, int entchannel) +{ +} + +sfx_t *S_PrecacheSound (char *sample) +{ + return NULL; +} + +void S_ClearPrecache (void) +{ +} + +void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up) +{ +} + +void S_StopAllSounds (qboolean clear) +{ +} + +void S_BeginPrecaching (void) +{ +} + +void S_EndPrecaching (void) +{ +} + +void S_ExtraUpdate (void) +{ +} + +void S_LocalSound (char *s) +{ +} + diff --git a/WinQuake/snd_sun.c b/WinQuake/snd_sun.c index fe9f8bb..0f0ec3f 100644 --- a/WinQuake/snd_sun.c +++ b/WinQuake/snd_sun.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #include #include #include diff --git a/WinQuake/snd_win.c b/WinQuake/snd_win.c index 11028c4..b0b2bf5 100644 --- a/WinQuake/snd_win.c +++ b/WinQuake/snd_win.c @@ -1,729 +1,729 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" -#include "winquake.h" - -#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) - -HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); - -// 64K is > 1 second at 16-bit, 22050 Hz -#define WAV_BUFFERS 64 -#define WAV_MASK 0x3F -#define WAV_BUFFER_SIZE 0x0400 -#define SECONDARY_BUFFER_SIZE 0x10000 - -typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat; - -static qboolean wavonly; -static qboolean dsound_init; -static qboolean wav_init; -static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; -static qboolean primary_format_set; - -static int sample16; -static int snd_sent, snd_completed; - - -/* - * Global variables. Must be visible to window-procedure function - * so it can unlock and free the data block after it has been played. - */ - -HANDLE hData; -HPSTR lpData, lpData2; - -HGLOBAL hWaveHdr; -LPWAVEHDR lpWaveHdr; - -HWAVEOUT hWaveOut; - -WAVEOUTCAPS wavecaps; - -DWORD gSndBufSize; - -MMTIME mmstarttime; - -LPDIRECTSOUND pDS; -LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; - -HINSTANCE hInstDS; - -qboolean SNDDMA_InitDirect (void); -qboolean SNDDMA_InitWav (void); - - -/* -================== -S_BlockSound -================== -*/ -void S_BlockSound (void) -{ - -// DirectSound takes care of blocking itself - if (snd_iswave) - { - snd_blocked++; - - if (snd_blocked == 1) - { - waveOutReset (hWaveOut); - } - } -} - - -/* -================== -S_UnblockSound -================== -*/ -void S_UnblockSound (void) -{ - -// DirectSound takes care of blocking itself - if (snd_iswave) - { - snd_blocked--; - } -} - - -/* -================== -FreeSound -================== -*/ -void FreeSound (void) -{ - int i; - - if (pDSBuf) - { - pDSBuf->lpVtbl->Stop(pDSBuf); - pDSBuf->lpVtbl->Release(pDSBuf); - } - -// only release primary buffer if it's not also the mixing buffer we just released - if (pDSPBuf && (pDSBuf != pDSPBuf)) - { - pDSPBuf->lpVtbl->Release(pDSPBuf); - } - - if (pDS) - { - pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); - pDS->lpVtbl->Release(pDS); - } - - if (hWaveOut) - { - waveOutReset (hWaveOut); - - if (lpWaveHdr) - { - for (i=0 ; i< WAV_BUFFERS ; i++) - waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); - } - - waveOutClose (hWaveOut); - - if (hWaveHdr) - { - GlobalUnlock(hWaveHdr); - GlobalFree(hWaveHdr); - } - - if (hData) - { - GlobalUnlock(hData); - GlobalFree(hData); - } - - } - - pDS = NULL; - pDSBuf = NULL; - pDSPBuf = NULL; - hWaveOut = 0; - hData = 0; - hWaveHdr = 0; - lpData = NULL; - lpWaveHdr = NULL; - dsound_init = false; - wav_init = false; -} - - -/* -================== -SNDDMA_InitDirect - -Direct-Sound support -================== -*/ -sndinitstat SNDDMA_InitDirect (void) -{ - DSBUFFERDESC dsbuf; - DSBCAPS dsbcaps; - DWORD dwSize, dwWrite; - DSCAPS dscaps; - WAVEFORMATEX format, pformat; - HRESULT hresult; - int reps; - - memset ((void *)&sn, 0, sizeof (sn)); - - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - shm->speed = 11025; - - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->speed; - format.nBlockAlign = format.nChannels - *format.wBitsPerSample / 8; - format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec - *format.nBlockAlign; - - if (!hInstDS) - { - hInstDS = LoadLibrary("dsound.dll"); - - if (hInstDS == NULL) - { - Con_SafePrintf ("Couldn't load dsound.dll\n"); - return SIS_FAILURE; - } - - pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); - - if (!pDirectSoundCreate) - { - Con_SafePrintf ("Couldn't get DS proc addr\n"); - return SIS_FAILURE; - } - } - - while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK) - { - if (hresult != DSERR_ALLOCATED) - { - Con_SafePrintf ("DirectSound create failed\n"); - return SIS_FAILURE; - } - - if (MessageBox (NULL, - "The sound hardware is in use by another app.\n\n" - "Select Retry to try to start sound again or Cancel to run Quake with no sound.", - "Sound not available", - MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) - { - Con_SafePrintf ("DirectSoundCreate failure\n" - " hardware already in use\n"); - return SIS_NOTAVAIL; - } - } - - dscaps.dwSize = sizeof(dscaps); - - if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) - { - Con_SafePrintf ("Couldn't get DS caps\n"); - } - - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) - { - Con_SafePrintf ("No DirectSound driver installed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (); - return SIS_FAILURE; - } - -// get access to the primary buffer, if possible, so we can set the -// sound hardware format - memset (&dsbuf, 0, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; - dsbuf.dwBufferBytes = 0; - dsbuf.lpwfxFormat = NULL; - - memset(&dsbcaps, 0, sizeof(dsbcaps)); - dsbcaps.dwSize = sizeof(dsbcaps); - primary_format_set = false; - - if (!COM_CheckParm ("-snoforceformat")) - { - if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) - { - pformat = format; - - if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) - { - if (snd_firsttime) - Con_SafePrintf ("Set primary sound buffer format: no\n"); - } - else - { - if (snd_firsttime) - Con_SafePrintf ("Set primary sound buffer format: yes\n"); - - primary_format_set = true; - } - } - } - - if (!primary_format_set || !COM_CheckParm ("-primarysound")) - { - // create the secondary buffer we'll actually work with - memset (&dsbuf, 0, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE; - dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; - dsbuf.lpwfxFormat = &format; - - memset(&dsbcaps, 0, sizeof(dsbcaps)); - dsbcaps.dwSize = sizeof(dsbcaps); - - if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) - { - Con_SafePrintf ("DS:CreateSoundBuffer Failed"); - FreeSound (); - return SIS_FAILURE; - } - - shm->channels = format.nChannels; - shm->samplebits = format.wBitsPerSample; - shm->speed = format.nSamplesPerSec; - - if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) - { - Con_SafePrintf ("DS:GetCaps failed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (snd_firsttime) - Con_SafePrintf ("Using secondary sound buffer\n"); - } - else - { - if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) - { - Con_SafePrintf ("Set coop level failed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) - { - Con_Printf ("DS:GetCaps failed\n"); - return SIS_FAILURE; - } - - pDSBuf = pDSPBuf; - Con_SafePrintf ("Using primary sound buffer\n"); - } - - // Make sure mixer is active - pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - - if (snd_firsttime) - Con_SafePrintf(" %d channel(s)\n" - " %d bits/sample\n" - " %d bytes/sec\n", - shm->channels, shm->samplebits, shm->speed); - - gSndBufSize = dsbcaps.dwBufferBytes; - -// initialize the buffer - reps = 0; - - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) - { - if (hresult != DSERR_BUFFERLOST) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); - FreeSound (); - return SIS_FAILURE; - } - - if (++reps > 10000) - { - Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); - FreeSound (); - return SIS_FAILURE; - } - - } - - memset(lpData, 0, dwSize); -// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging - - pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); - - /* we don't want anyone to access the buffer directly w/o locking it first. */ - lpData = NULL; - - pDSBuf->lpVtbl->Stop(pDSBuf); - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); - pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - - shm->soundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) lpData; - sample16 = (shm->samplebits/8) - 1; - - dsound_init = true; - - return SIS_SUCCESS; -} - - -/* -================== -SNDDM_InitWav - -Crappy windows multimedia base -================== -*/ -qboolean SNDDMA_InitWav (void) -{ - WAVEFORMATEX format; - int i; - HRESULT hr; - - snd_sent = 0; - snd_completed = 0; - - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - shm->speed = 11025; - - memset (&format, 0, sizeof(format)); - format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->speed; - format.nBlockAlign = format.nChannels - *format.wBitsPerSample / 8; - format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec - *format.nBlockAlign; - - /* Open a waveform device for output using window callback. */ - while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, - &format, - 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) - { - if (hr != MMSYSERR_ALLOCATED) - { - Con_SafePrintf ("waveOutOpen failed\n"); - return false; - } - - if (MessageBox (NULL, - "The sound hardware is in use by another app.\n\n" - "Select Retry to try to start sound again or Cancel to run Quake with no sound.", - "Sound not available", - MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) - { - Con_SafePrintf ("waveOutOpen failure;\n" - " hardware already in use\n"); - return false; - } - } - - /* - * Allocate and lock memory for the waveform data. The memory - * for waveform data must be globally allocated with - * GMEM_MOVEABLE and GMEM_SHARE flags. - - */ - gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; - hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); - if (!hData) - { - Con_SafePrintf ("Sound: Out of memory.\n"); - FreeSound (); - return false; - } - lpData = GlobalLock(hData); - if (!lpData) - { - Con_SafePrintf ("Sound: Failed to lock.\n"); - FreeSound (); - return false; - } - memset (lpData, 0, gSndBufSize); - - /* - * Allocate and lock memory for the header. This memory must - * also be globally allocated with GMEM_MOVEABLE and - * GMEM_SHARE flags. - */ - hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, - (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); - - if (hWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to Alloc header.\n"); - FreeSound (); - return false; - } - - lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); - - if (lpWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to lock header.\n"); - FreeSound (); - return false; - } - - memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); - - /* After allocation, set up and prepare headers. */ - for (i=0 ; isoundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) lpData; - sample16 = (shm->samplebits/8) - 1; - - wav_init = true; - - return true; -} - -/* -================== -SNDDMA_Init - -Try to find a sound device to mix for. -Returns false if nothing is found. -================== -*/ - -int SNDDMA_Init(void) -{ - sndinitstat stat; - - if (COM_CheckParm ("-wavonly")) - wavonly = true; - - dsound_init = wav_init = 0; - - stat = SIS_FAILURE; // assume DirectSound won't initialize - - /* Init DirectSound */ - if (!wavonly) - { - if (snd_firsttime || snd_isdirect) - { - stat = SNDDMA_InitDirect ();; - - if (stat == SIS_SUCCESS) - { - snd_isdirect = true; - - if (snd_firsttime) - Con_SafePrintf ("DirectSound initialized\n"); - } - else - { - snd_isdirect = false; - Con_SafePrintf ("DirectSound failed to init\n"); - } - } - } - -// if DirectSound didn't succeed in initializing, try to initialize -// waveOut sound, unless DirectSound failed because the hardware is -// already allocated (in which case the user has already chosen not -// to have sound) - if (!dsound_init && (stat != SIS_NOTAVAIL)) - { - if (snd_firsttime || snd_iswave) - { - - snd_iswave = SNDDMA_InitWav (); - - if (snd_iswave) - { - if (snd_firsttime) - Con_SafePrintf ("Wave sound initialized\n"); - } - else - { - Con_SafePrintf ("Wave sound failed to init\n"); - } - } - } - - snd_firsttime = false; - - if (!dsound_init && !wav_init) - { - if (snd_firsttime) - Con_SafePrintf ("No sound device initialized\n"); - - return 0; - } - - return 1; -} - -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos(void) -{ - MMTIME mmtime; - int s; - DWORD dwWrite; - - if (dsound_init) - { - mmtime.wType = TIME_SAMPLES; - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); - s = mmtime.u.sample - mmstarttime.u.sample; - } - else if (wav_init) - { - s = snd_sent * WAV_BUFFER_SIZE; - } - - - s >>= sample16; - - s &= (shm->samples-1); - - return s; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -=============== -*/ -void SNDDMA_Submit(void) -{ - LPWAVEHDR h; - int wResult; - - if (!wav_init) - return; - - // - // find which sound blocks have completed - // - while (1) - { - if ( snd_completed == snd_sent ) - { - Con_DPrintf ("Sound overrun\n"); - break; - } - - if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) - { - break; - } - - snd_completed++; // this buffer has been played - } - - // - // submit two new sound blocks - // - while (((snd_sent - snd_completed) >> sample16) < 4) - { - h = lpWaveHdr + ( snd_sent&WAV_MASK ); - - snd_sent++; - /* - * Now the data block can be sent to the output device. The - * waveOutWrite function returns immediately and waveform - * data is sent to the output device in the background. - */ - wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); - - if (wResult != MMSYSERR_NOERROR) - { - Con_SafePrintf ("Failed to write block to device\n"); - FreeSound (); - return; - } - } -} - -/* -============== -SNDDMA_Shutdown - -Reset the sound device for exiting -=============== -*/ -void SNDDMA_Shutdown(void) -{ - FreeSound (); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "quakedef.h" +#include "winquake.h" + +#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) + +HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); + +// 64K is > 1 second at 16-bit, 22050 Hz +#define WAV_BUFFERS 64 +#define WAV_MASK 0x3F +#define WAV_BUFFER_SIZE 0x0400 +#define SECONDARY_BUFFER_SIZE 0x10000 + +typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat; + +static qboolean wavonly; +static qboolean dsound_init; +static qboolean wav_init; +static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; +static qboolean primary_format_set; + +static int sample16; +static int snd_sent, snd_completed; + + +/* + * Global variables. Must be visible to window-procedure function + * so it can unlock and free the data block after it has been played. + */ + +HANDLE hData; +HPSTR lpData, lpData2; + +HGLOBAL hWaveHdr; +LPWAVEHDR lpWaveHdr; + +HWAVEOUT hWaveOut; + +WAVEOUTCAPS wavecaps; + +DWORD gSndBufSize; + +MMTIME mmstarttime; + +LPDIRECTSOUND pDS; +LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; + +HINSTANCE hInstDS; + +qboolean SNDDMA_InitDirect (void); +qboolean SNDDMA_InitWav (void); + + +/* +================== +S_BlockSound +================== +*/ +void S_BlockSound (void) +{ + +// DirectSound takes care of blocking itself + if (snd_iswave) + { + snd_blocked++; + + if (snd_blocked == 1) + { + waveOutReset (hWaveOut); + } + } +} + + +/* +================== +S_UnblockSound +================== +*/ +void S_UnblockSound (void) +{ + +// DirectSound takes care of blocking itself + if (snd_iswave) + { + snd_blocked--; + } +} + + +/* +================== +FreeSound +================== +*/ +void FreeSound (void) +{ + int i; + + if (pDSBuf) + { + pDSBuf->lpVtbl->Stop(pDSBuf); + pDSBuf->lpVtbl->Release(pDSBuf); + } + +// only release primary buffer if it's not also the mixing buffer we just released + if (pDSPBuf && (pDSBuf != pDSPBuf)) + { + pDSPBuf->lpVtbl->Release(pDSPBuf); + } + + if (pDS) + { + pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); + pDS->lpVtbl->Release(pDS); + } + + if (hWaveOut) + { + waveOutReset (hWaveOut); + + if (lpWaveHdr) + { + for (i=0 ; i< WAV_BUFFERS ; i++) + waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); + } + + waveOutClose (hWaveOut); + + if (hWaveHdr) + { + GlobalUnlock(hWaveHdr); + GlobalFree(hWaveHdr); + } + + if (hData) + { + GlobalUnlock(hData); + GlobalFree(hData); + } + + } + + pDS = NULL; + pDSBuf = NULL; + pDSPBuf = NULL; + hWaveOut = 0; + hData = 0; + hWaveHdr = 0; + lpData = NULL; + lpWaveHdr = NULL; + dsound_init = false; + wav_init = false; +} + + +/* +================== +SNDDMA_InitDirect + +Direct-Sound support +================== +*/ +sndinitstat SNDDMA_InitDirect (void) +{ + DSBUFFERDESC dsbuf; + DSBCAPS dsbcaps; + DWORD dwSize, dwWrite; + DSCAPS dscaps; + WAVEFORMATEX format, pformat; + HRESULT hresult; + int reps; + + memset ((void *)&sn, 0, sizeof (sn)); + + shm = &sn; + + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 11025; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = shm->channels; + format.wBitsPerSample = shm->samplebits; + format.nSamplesPerSec = shm->speed; + format.nBlockAlign = format.nChannels + *format.wBitsPerSample / 8; + format.cbSize = 0; + format.nAvgBytesPerSec = format.nSamplesPerSec + *format.nBlockAlign; + + if (!hInstDS) + { + hInstDS = LoadLibrary("dsound.dll"); + + if (hInstDS == NULL) + { + Con_SafePrintf ("Couldn't load dsound.dll\n"); + return SIS_FAILURE; + } + + pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate"); + + if (!pDirectSoundCreate) + { + Con_SafePrintf ("Couldn't get DS proc addr\n"); + return SIS_FAILURE; + } + } + + while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK) + { + if (hresult != DSERR_ALLOCATED) + { + Con_SafePrintf ("DirectSound create failed\n"); + return SIS_FAILURE; + } + + if (MessageBox (NULL, + "The sound hardware is in use by another app.\n\n" + "Select Retry to try to start sound again or Cancel to run Quake with no sound.", + "Sound not available", + MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) + { + Con_SafePrintf ("DirectSoundCreate failure\n" + " hardware already in use\n"); + return SIS_NOTAVAIL; + } + } + + dscaps.dwSize = sizeof(dscaps); + + if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) + { + Con_SafePrintf ("Couldn't get DS caps\n"); + } + + if (dscaps.dwFlags & DSCAPS_EMULDRIVER) + { + Con_SafePrintf ("No DirectSound driver installed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) + { + Con_SafePrintf ("Set coop level failed\n"); + FreeSound (); + return SIS_FAILURE; + } + +// get access to the primary buffer, if possible, so we can set the +// sound hardware format + memset (&dsbuf, 0, sizeof(dsbuf)); + dsbuf.dwSize = sizeof(DSBUFFERDESC); + dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbuf.dwBufferBytes = 0; + dsbuf.lpwfxFormat = NULL; + + memset(&dsbcaps, 0, sizeof(dsbcaps)); + dsbcaps.dwSize = sizeof(dsbcaps); + primary_format_set = false; + + if (!COM_CheckParm ("-snoforceformat")) + { + if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) + { + pformat = format; + + if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) + { + if (snd_firsttime) + Con_SafePrintf ("Set primary sound buffer format: no\n"); + } + else + { + if (snd_firsttime) + Con_SafePrintf ("Set primary sound buffer format: yes\n"); + + primary_format_set = true; + } + } + } + + if (!primary_format_set || !COM_CheckParm ("-primarysound")) + { + // create the secondary buffer we'll actually work with + memset (&dsbuf, 0, sizeof(dsbuf)); + dsbuf.dwSize = sizeof(DSBUFFERDESC); + dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE; + dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; + dsbuf.lpwfxFormat = &format; + + memset(&dsbcaps, 0, sizeof(dsbcaps)); + dsbcaps.dwSize = sizeof(dsbcaps); + + if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) + { + Con_SafePrintf ("DS:CreateSoundBuffer Failed"); + FreeSound (); + return SIS_FAILURE; + } + + shm->channels = format.nChannels; + shm->samplebits = format.wBitsPerSample; + shm->speed = format.nSamplesPerSec; + + if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) + { + Con_SafePrintf ("DS:GetCaps failed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (snd_firsttime) + Con_SafePrintf ("Using secondary sound buffer\n"); + } + else + { + if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) + { + Con_SafePrintf ("Set coop level failed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) + { + Con_Printf ("DS:GetCaps failed\n"); + return SIS_FAILURE; + } + + pDSBuf = pDSPBuf; + Con_SafePrintf ("Using primary sound buffer\n"); + } + + // Make sure mixer is active + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + + if (snd_firsttime) + Con_SafePrintf(" %d channel(s)\n" + " %d bits/sample\n" + " %d bytes/sec\n", + shm->channels, shm->samplebits, shm->speed); + + gSndBufSize = dsbcaps.dwBufferBytes; + +// initialize the buffer + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); + FreeSound (); + return SIS_FAILURE; + } + + if (++reps > 10000) + { + Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); + FreeSound (); + return SIS_FAILURE; + } + + } + + memset(lpData, 0, dwSize); +// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging + + pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); + + /* we don't want anyone to access the buffer directly w/o locking it first. */ + lpData = NULL; + + pDSBuf->lpVtbl->Stop(pDSBuf); + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + + shm->soundalive = true; + shm->splitbuffer = false; + shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) lpData; + sample16 = (shm->samplebits/8) - 1; + + dsound_init = true; + + return SIS_SUCCESS; +} + + +/* +================== +SNDDM_InitWav + +Crappy windows multimedia base +================== +*/ +qboolean SNDDMA_InitWav (void) +{ + WAVEFORMATEX format; + int i; + HRESULT hr; + + snd_sent = 0; + snd_completed = 0; + + shm = &sn; + + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 11025; + + memset (&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = shm->channels; + format.wBitsPerSample = shm->samplebits; + format.nSamplesPerSec = shm->speed; + format.nBlockAlign = format.nChannels + *format.wBitsPerSample / 8; + format.cbSize = 0; + format.nAvgBytesPerSec = format.nSamplesPerSec + *format.nBlockAlign; + + /* Open a waveform device for output using window callback. */ + while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, + &format, + 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) + { + if (hr != MMSYSERR_ALLOCATED) + { + Con_SafePrintf ("waveOutOpen failed\n"); + return false; + } + + if (MessageBox (NULL, + "The sound hardware is in use by another app.\n\n" + "Select Retry to try to start sound again or Cancel to run Quake with no sound.", + "Sound not available", + MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) + { + Con_SafePrintf ("waveOutOpen failure;\n" + " hardware already in use\n"); + return false; + } + } + + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + + */ + gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; + hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); + if (!hData) + { + Con_SafePrintf ("Sound: Out of memory.\n"); + FreeSound (); + return false; + } + lpData = GlobalLock(hData); + if (!lpData) + { + Con_SafePrintf ("Sound: Failed to lock.\n"); + FreeSound (); + return false; + } + memset (lpData, 0, gSndBufSize); + + /* + * Allocate and lock memory for the header. This memory must + * also be globally allocated with GMEM_MOVEABLE and + * GMEM_SHARE flags. + */ + hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); + + if (hWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to Alloc header.\n"); + FreeSound (); + return false; + } + + lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); + + if (lpWaveHdr == NULL) + { + Con_SafePrintf ("Sound: Failed to lock header.\n"); + FreeSound (); + return false; + } + + memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); + + /* After allocation, set up and prepare headers. */ + for (i=0 ; isoundalive = true; + shm->splitbuffer = false; + shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char *) lpData; + sample16 = (shm->samplebits/8) - 1; + + wav_init = true; + + return true; +} + +/* +================== +SNDDMA_Init + +Try to find a sound device to mix for. +Returns false if nothing is found. +================== +*/ + +int SNDDMA_Init(void) +{ + sndinitstat stat; + + if (COM_CheckParm ("-wavonly")) + wavonly = true; + + dsound_init = wav_init = 0; + + stat = SIS_FAILURE; // assume DirectSound won't initialize + + /* Init DirectSound */ + if (!wavonly) + { + if (snd_firsttime || snd_isdirect) + { + stat = SNDDMA_InitDirect ();; + + if (stat == SIS_SUCCESS) + { + snd_isdirect = true; + + if (snd_firsttime) + Con_SafePrintf ("DirectSound initialized\n"); + } + else + { + snd_isdirect = false; + Con_SafePrintf ("DirectSound failed to init\n"); + } + } + } + +// if DirectSound didn't succeed in initializing, try to initialize +// waveOut sound, unless DirectSound failed because the hardware is +// already allocated (in which case the user has already chosen not +// to have sound) + if (!dsound_init && (stat != SIS_NOTAVAIL)) + { + if (snd_firsttime || snd_iswave) + { + + snd_iswave = SNDDMA_InitWav (); + + if (snd_iswave) + { + if (snd_firsttime) + Con_SafePrintf ("Wave sound initialized\n"); + } + else + { + Con_SafePrintf ("Wave sound failed to init\n"); + } + } + } + + snd_firsttime = false; + + if (!dsound_init && !wav_init) + { + if (snd_firsttime) + Con_SafePrintf ("No sound device initialized\n"); + + return 0; + } + + return 1; +} + +/* +============== +SNDDMA_GetDMAPos + +return the current sample position (in mono samples read) +inside the recirculating dma buffer, so the mixing code will know +how many sample are required to fill it up. +=============== +*/ +int SNDDMA_GetDMAPos(void) +{ + MMTIME mmtime; + int s; + DWORD dwWrite; + + if (dsound_init) + { + mmtime.wType = TIME_SAMPLES; + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); + s = mmtime.u.sample - mmstarttime.u.sample; + } + else if (wav_init) + { + s = snd_sent * WAV_BUFFER_SIZE; + } + + + s >>= sample16; + + s &= (shm->samples-1); + + return s; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(void) +{ + LPWAVEHDR h; + int wResult; + + if (!wav_init) + return; + + // + // find which sound blocks have completed + // + while (1) + { + if ( snd_completed == snd_sent ) + { + Con_DPrintf ("Sound overrun\n"); + break; + } + + if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) + { + break; + } + + snd_completed++; // this buffer has been played + } + + // + // submit two new sound blocks + // + while (((snd_sent - snd_completed) >> sample16) < 4) + { + h = lpWaveHdr + ( snd_sent&WAV_MASK ); + + snd_sent++; + /* + * Now the data block can be sent to the output device. The + * waveOutWrite function returns immediately and waveform + * data is sent to the output device in the background. + */ + wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); + + if (wResult != MMSYSERR_NOERROR) + { + Con_SafePrintf ("Failed to write block to device\n"); + FreeSound (); + return; + } + } +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown(void) +{ + FreeSound (); +} + diff --git a/WinQuake/sound.h b/WinQuake/sound.h index 1ba08d3..6410af2 100644 --- a/WinQuake/sound.h +++ b/WinQuake/sound.h @@ -1,177 +1,177 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sound.h -- client sound i/o functions - -#ifndef __SOUND__ -#define __SOUND__ - -#define DEFAULT_SOUND_PACKET_VOLUME 255 -#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 - -// !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct -{ - int left; - int right; -} portable_samplepair_t; - -typedef struct sfx_s -{ - char name[MAX_QPATH]; - cache_user_t cache; -} sfx_t; - -// !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct -{ - int length; - int loopstart; - int speed; - int width; - int stereo; - byte data[1]; // variable sized -} sfxcache_t; - -typedef struct -{ - qboolean gamealive; - qboolean soundalive; - qboolean splitbuffer; - int channels; - int samples; // mono samples in buffer - int submission_chunk; // don't mix less than this # - int samplepos; // in mono samples - int samplebits; - int speed; - unsigned char *buffer; -} dma_t; - -// !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct -{ - sfx_t *sfx; // sfx number - int leftvol; // 0-255 volume - int rightvol; // 0-255 volume - int end; // end time in global paintsamples - int pos; // sample position in sfx - int looping; // where to loop, -1 = no looping - int entnum; // to allow overriding a specific sound - int entchannel; // - vec3_t origin; // origin of sound effect - vec_t dist_mult; // distance multiplier (attenuation/clipK) - int master_vol; // 0-255 master volume -} channel_t; - -typedef struct -{ - int rate; - int width; - int channels; - int loopstart; - int samples; - int dataofs; // chunk starts this many bytes from file start -} wavinfo_t; - -void S_Init (void); -void S_Startup (void); -void S_Shutdown (void); -void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation); -void S_StopSound (int entnum, int entchannel); -void S_StopAllSounds(qboolean clear); -void S_ClearBuffer (void); -void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); -void S_ExtraUpdate (void); - -sfx_t *S_PrecacheSound (char *sample); -void S_TouchSound (char *sample); -void S_ClearPrecache (void); -void S_BeginPrecaching (void); -void S_EndPrecaching (void); -void S_PaintChannels(int endtime); -void S_InitPaintChannels (void); - -// picks a channel based on priorities, empty slots, number of channels -channel_t *SND_PickChannel(int entnum, int entchannel); - -// spatializes a channel -void SND_Spatialize(channel_t *ch); - -// initializes cycling through a DMA buffer and returns information on it -qboolean SNDDMA_Init(void); - -// gets the current DMA position -int SNDDMA_GetDMAPos(void); - -// shutdown the DMA xfer. -void SNDDMA_Shutdown(void); - -// ==================================================================== -// User-setable variables -// ==================================================================== - -#define MAX_CHANNELS 128 -#define MAX_DYNAMIC_CHANNELS 8 - - -extern channel_t channels[MAX_CHANNELS]; -// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds -// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc -// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds - -extern int total_channels; - -// -// Fake dma is a synchronous faking of the DMA progress used for -// isolating performance in the renderer. The fakedma_updates is -// number of times S_Update() is called per second. -// - -extern qboolean fakedma; -extern int fakedma_updates; -extern int paintedtime; -extern vec3_t listener_origin; -extern vec3_t listener_forward; -extern vec3_t listener_right; -extern vec3_t listener_up; -extern volatile dma_t *shm; -extern volatile dma_t sn; -extern vec_t sound_nominal_clip_dist; - -extern cvar_t loadas8bit; -extern cvar_t bgmvolume; -extern cvar_t volume; - -extern qboolean snd_initialized; - -extern int snd_blocked; - -void S_LocalSound (char *s); -sfxcache_t *S_LoadSound (sfx_t *s); - -wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength); - -void SND_InitScaletable (void); -void SNDDMA_Submit(void); - -void S_AmbientOff (void); -void S_AmbientOn (void); - -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sound.h -- client sound i/o functions + +#ifndef __SOUND__ +#define __SOUND__ + +#define DEFAULT_SOUND_PACKET_VOLUME 255 +#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 + +// !!! if this is changed, it much be changed in asm_i386.h too !!! +typedef struct +{ + int left; + int right; +} portable_samplepair_t; + +typedef struct sfx_s +{ + char name[MAX_QPATH]; + cache_user_t cache; +} sfx_t; + +// !!! if this is changed, it much be changed in asm_i386.h too !!! +typedef struct +{ + int length; + int loopstart; + int speed; + int width; + int stereo; + byte data[1]; // variable sized +} sfxcache_t; + +typedef struct +{ + qboolean gamealive; + qboolean soundalive; + qboolean splitbuffer; + int channels; + int samples; // mono samples in buffer + int submission_chunk; // don't mix less than this # + int samplepos; // in mono samples + int samplebits; + int speed; + unsigned char *buffer; +} dma_t; + +// !!! if this is changed, it much be changed in asm_i386.h too !!! +typedef struct +{ + sfx_t *sfx; // sfx number + int leftvol; // 0-255 volume + int rightvol; // 0-255 volume + int end; // end time in global paintsamples + int pos; // sample position in sfx + int looping; // where to loop, -1 = no looping + int entnum; // to allow overriding a specific sound + int entchannel; // + vec3_t origin; // origin of sound effect + vec_t dist_mult; // distance multiplier (attenuation/clipK) + int master_vol; // 0-255 master volume +} channel_t; + +typedef struct +{ + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start +} wavinfo_t; + +void S_Init (void); +void S_Startup (void); +void S_Shutdown (void); +void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); +void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation); +void S_StopSound (int entnum, int entchannel); +void S_StopAllSounds(qboolean clear); +void S_ClearBuffer (void); +void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); +void S_ExtraUpdate (void); + +sfx_t *S_PrecacheSound (char *sample); +void S_TouchSound (char *sample); +void S_ClearPrecache (void); +void S_BeginPrecaching (void); +void S_EndPrecaching (void); +void S_PaintChannels(int endtime); +void S_InitPaintChannels (void); + +// picks a channel based on priorities, empty slots, number of channels +channel_t *SND_PickChannel(int entnum, int entchannel); + +// spatializes a channel +void SND_Spatialize(channel_t *ch); + +// initializes cycling through a DMA buffer and returns information on it +qboolean SNDDMA_Init(void); + +// gets the current DMA position +int SNDDMA_GetDMAPos(void); + +// shutdown the DMA xfer. +void SNDDMA_Shutdown(void); + +// ==================================================================== +// User-setable variables +// ==================================================================== + +#define MAX_CHANNELS 128 +#define MAX_DYNAMIC_CHANNELS 8 + + +extern channel_t channels[MAX_CHANNELS]; +// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds +// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc +// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds + +extern int total_channels; + +// +// Fake dma is a synchronous faking of the DMA progress used for +// isolating performance in the renderer. The fakedma_updates is +// number of times S_Update() is called per second. +// + +extern qboolean fakedma; +extern int fakedma_updates; +extern int paintedtime; +extern vec3_t listener_origin; +extern vec3_t listener_forward; +extern vec3_t listener_right; +extern vec3_t listener_up; +extern volatile dma_t *shm; +extern volatile dma_t sn; +extern vec_t sound_nominal_clip_dist; + +extern cvar_t loadas8bit; +extern cvar_t bgmvolume; +extern cvar_t volume; + +extern qboolean snd_initialized; + +extern int snd_blocked; + +void S_LocalSound (char *s); +sfxcache_t *S_LoadSound (sfx_t *s); + +wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength); + +void SND_InitScaletable (void); +void SNDDMA_Submit(void); + +void S_AmbientOff (void); +void S_AmbientOn (void); + +#endif diff --git a/WinQuake/spritegn.h b/WinQuake/spritegn.h index b192b54..337c1d6 100644 --- a/WinQuake/spritegn.h +++ b/WinQuake/spritegn.h @@ -1,110 +1,110 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// spritegn.h: header file for sprite generation program -// - -// ********************************************************** -// * This file must be identical in the spritegen directory * -// * and in the Quake directory, because it's used to * -// * pass data from one to the other via .spr files. * -// ********************************************************** - -//------------------------------------------------------- -// This program generates .spr sprite package files. -// The format of the files is as follows: -// -// dsprite_t file header structure -// -// -// dspriteframe_t frame header structure -// sprite bitmap -// -// dspriteframe_t frame header structure -// sprite bitmap -// -//------------------------------------------------------- - -#ifdef INCLUDELIBS - -#include -#include -#include -#include - -#include "cmdlib.h" -#include "scriplib.h" -#include "dictlib.h" -#include "trilib.h" -#include "lbmlib.h" -#include "mathlib.h" - -#endif - -#define SPRITE_VERSION 1 - -// must match definition in modelgen.h -#ifndef SYNCTYPE_T -#define SYNCTYPE_T -typedef enum {ST_SYNC=0, ST_RAND } synctype_t; -#endif - -// TODO: shorten these? -typedef struct { - int ident; - int version; - int type; - float boundingradius; - int width; - int height; - int numframes; - float beamlength; - synctype_t synctype; -} dsprite_t; - -#define SPR_VP_PARALLEL_UPRIGHT 0 -#define SPR_FACING_UPRIGHT 1 -#define SPR_VP_PARALLEL 2 -#define SPR_ORIENTED 3 -#define SPR_VP_PARALLEL_ORIENTED 4 - -typedef struct { - int origin[2]; - int width; - int height; -} dspriteframe_t; - -typedef struct { - int numframes; -} dspritegroup_t; - -typedef struct { - float interval; -} dspriteinterval_t; - -typedef enum { SPR_SINGLE=0, SPR_GROUP } spriteframetype_t; - -typedef struct { - spriteframetype_t type; -} dspriteframetype_t; - -#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') - // little-endian "IDSP" - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// spritegn.h: header file for sprite generation program +// + +// ********************************************************** +// * This file must be identical in the spritegen directory * +// * and in the Quake directory, because it's used to * +// * pass data from one to the other via .spr files. * +// ********************************************************** + +//------------------------------------------------------- +// This program generates .spr sprite package files. +// The format of the files is as follows: +// +// dsprite_t file header structure +// +// +// dspriteframe_t frame header structure +// sprite bitmap +// +// dspriteframe_t frame header structure +// sprite bitmap +// +//------------------------------------------------------- + +#ifdef INCLUDELIBS + +#include +#include +#include +#include + +#include "cmdlib.h" +#include "scriplib.h" +#include "dictlib.h" +#include "trilib.h" +#include "lbmlib.h" +#include "mathlib.h" + +#endif + +#define SPRITE_VERSION 1 + +// must match definition in modelgen.h +#ifndef SYNCTYPE_T +#define SYNCTYPE_T +typedef enum {ST_SYNC=0, ST_RAND } synctype_t; +#endif + +// TODO: shorten these? +typedef struct { + int ident; + int version; + int type; + float boundingradius; + int width; + int height; + int numframes; + float beamlength; + synctype_t synctype; +} dsprite_t; + +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + +typedef struct { + int origin[2]; + int width; + int height; +} dspriteframe_t; + +typedef struct { + int numframes; +} dspritegroup_t; + +typedef struct { + float interval; +} dspriteinterval_t; + +typedef enum { SPR_SINGLE=0, SPR_GROUP } spriteframetype_t; + +typedef struct { + spriteframetype_t type; +} dspriteframetype_t; + +#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') + // little-endian "IDSP" + diff --git a/WinQuake/surf16.s b/WinQuake/surf16.s index c0812a3..8fffc40 100644 --- a/WinQuake/surf16.s +++ b/WinQuake/surf16.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // surf16.s // x86 assembly-language 16 bpp surface block drawing code. diff --git a/WinQuake/surf8.s b/WinQuake/surf8.s index a079f1d..7229e15 100644 --- a/WinQuake/surf8.s +++ b/WinQuake/surf8.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // surf8.s // x86 assembly-language 8 bpp surface block drawing code. diff --git a/WinQuake/sv_main.c b/WinQuake/sv_main.c index deda690..ae38b18 100644 --- a/WinQuake/sv_main.c +++ b/WinQuake/sv_main.c @@ -1,1200 +1,1200 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_main.c -- server main program - -#include "quakedef.h" - -server_t sv; -server_static_t svs; - -char localmodels[MAX_MODELS][5]; // inline model names for precache - -//============================================================================ - -/* -=============== -SV_Init -=============== -*/ -void SV_Init (void) -{ - int i; - extern cvar_t sv_maxvelocity; - extern cvar_t sv_gravity; - extern cvar_t sv_nostep; - extern cvar_t sv_friction; - extern cvar_t sv_edgefriction; - extern cvar_t sv_stopspeed; - extern cvar_t sv_maxspeed; - extern cvar_t sv_accelerate; - extern cvar_t sv_idealpitchscale; - extern cvar_t sv_aim; - - Cvar_RegisterVariable (&sv_maxvelocity); - Cvar_RegisterVariable (&sv_gravity); - Cvar_RegisterVariable (&sv_friction); - Cvar_RegisterVariable (&sv_edgefriction); - Cvar_RegisterVariable (&sv_stopspeed); - Cvar_RegisterVariable (&sv_maxspeed); - Cvar_RegisterVariable (&sv_accelerate); - Cvar_RegisterVariable (&sv_idealpitchscale); - Cvar_RegisterVariable (&sv_aim); - Cvar_RegisterVariable (&sv_nostep); - - for (i=0 ; i MAX_DATAGRAM-16) - return; - MSG_WriteByte (&sv.datagram, svc_particle); - MSG_WriteCoord (&sv.datagram, org[0]); - MSG_WriteCoord (&sv.datagram, org[1]); - MSG_WriteCoord (&sv.datagram, org[2]); - for (i=0 ; i<3 ; i++) - { - v = dir[i]*16; - if (v > 127) - v = 127; - else if (v < -128) - v = -128; - MSG_WriteChar (&sv.datagram, v); - } - MSG_WriteByte (&sv.datagram, count); - MSG_WriteByte (&sv.datagram, color); -} - -/* -================== -SV_StartSound - -Each entity can have eight independant sound sources, like voice, -weapon, feet, etc. - -Channel 0 is an auto-allocate channel, the others override anything -allready running on that entity/channel pair. - -An attenuation of 0 will play full volume everywhere in the level. -Larger attenuations will drop off. (max 4 attenuation) - -================== -*/ -void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, - float attenuation) -{ - int sound_num; - int field_mask; - int i; - int ent; - - if (volume < 0 || volume > 255) - Sys_Error ("SV_StartSound: volume = %i", volume); - - if (attenuation < 0 || attenuation > 4) - Sys_Error ("SV_StartSound: attenuation = %f", attenuation); - - if (channel < 0 || channel > 7) - Sys_Error ("SV_StartSound: channel = %i", channel); - - if (sv.datagram.cursize > MAX_DATAGRAM-16) - return; - -// find precache number for sound - for (sound_num=1 ; sound_numv.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i])); -} - -/* -============================================================================== - -CLIENT SPAWNING - -============================================================================== -*/ - -/* -================ -SV_SendServerinfo - -Sends the first message from the server to a connected client. -This will be sent on the initial connection and upon each server load. -================ -*/ -void SV_SendServerinfo (client_t *client) -{ - char **s; - char message[2048]; - - MSG_WriteByte (&client->message, svc_print); - sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc); - MSG_WriteString (&client->message,message); - - MSG_WriteByte (&client->message, svc_serverinfo); - MSG_WriteLong (&client->message, PROTOCOL_VERSION); - MSG_WriteByte (&client->message, svs.maxclients); - - if (!coop.value && deathmatch.value) - MSG_WriteByte (&client->message, GAME_DEATHMATCH); - else - MSG_WriteByte (&client->message, GAME_COOP); - - sprintf (message, pr_strings+sv.edicts->v.message); - - MSG_WriteString (&client->message,message); - - for (s = sv.model_precache+1 ; *s ; s++) - MSG_WriteString (&client->message, *s); - MSG_WriteByte (&client->message, 0); - - for (s = sv.sound_precache+1 ; *s ; s++) - MSG_WriteString (&client->message, *s); - MSG_WriteByte (&client->message, 0); - -// send music - MSG_WriteByte (&client->message, svc_cdtrack); - MSG_WriteByte (&client->message, sv.edicts->v.sounds); - MSG_WriteByte (&client->message, sv.edicts->v.sounds); - -// set view - MSG_WriteByte (&client->message, svc_setview); - MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict)); - - MSG_WriteByte (&client->message, svc_signonnum); - MSG_WriteByte (&client->message, 1); - - client->sendsignon = true; - client->spawned = false; // need prespawn, spawn, etc -} - -/* -================ -SV_ConnectClient - -Initializes a client_t for a new net connection. This will only be called -once for a player each game, not once for each level change. -================ -*/ -void SV_ConnectClient (int clientnum) -{ - edict_t *ent; - client_t *client; - int edictnum; - struct qsocket_s *netconnection; - int i; - float spawn_parms[NUM_SPAWN_PARMS]; - - client = svs.clients + clientnum; - - Con_DPrintf ("Client %s connected\n", client->netconnection->address); - - edictnum = clientnum+1; - - ent = EDICT_NUM(edictnum); - -// set up the client_t - netconnection = client->netconnection; - - if (sv.loadgame) - memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms)); - memset (client, 0, sizeof(*client)); - client->netconnection = netconnection; - - strcpy (client->name, "unconnected"); - client->active = true; - client->spawned = false; - client->edict = ent; - client->message.data = client->msgbuf; - client->message.maxsize = sizeof(client->msgbuf); - client->message.allowoverflow = true; // we can catch it - -#ifdef IDGODS - client->privileged = IsID(&client->netconnection->addr); -#else - client->privileged = false; -#endif - - if (sv.loadgame) - memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms)); - else - { - // call the progs to get default spawn parms for the new client - PR_ExecuteProgram (pr_global_struct->SetNewParms); - for (i=0 ; ispawn_parms[i] = (&pr_global_struct->parm1)[i]; - } - - SV_SendServerinfo (client); -} - - -/* -=================== -SV_CheckForNewClients - -=================== -*/ -void SV_CheckForNewClients (void) -{ - struct qsocket_s *ret; - int i; - -// -// check for new connections -// - while (1) - { - ret = NET_CheckNewConnections (); - if (!ret) - break; - - // - // init a new client structure - // - for (i=0 ; icontents < 0) - { - if (node->contents != CONTENTS_SOLID) - { - pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel); - for (i=0 ; iplane; - d = DotProduct (org, plane->normal) - plane->dist; - if (d > 8) - node = node->children[0]; - else if (d < -8) - node = node->children[1]; - else - { // go down both - SV_AddToFatPVS (org, node->children[0]); - node = node->children[1]; - } - } -} - -/* -============= -SV_FatPVS - -Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the -given point. -============= -*/ -byte *SV_FatPVS (vec3_t org) -{ - fatbytes = (sv.worldmodel->numleafs+31)>>3; - Q_memset (fatpvs, 0, fatbytes); - SV_AddToFatPVS (org, sv.worldmodel->nodes); - return fatpvs; -} - -//============================================================================= - - -/* -============= -SV_WriteEntitiesToClient - -============= -*/ -void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) -{ - int e, i; - int bits; - byte *pvs; - vec3_t org; - float miss; - edict_t *ent; - -// find the client's PVS - VectorAdd (clent->v.origin, clent->v.view_ofs, org); - pvs = SV_FatPVS (org); - -// send over all entities (excpet the client) that touch the pvs - ent = NEXT_EDICT(sv.edicts); - for (e=1 ; ev.effects == EF_NODRAW) - continue; -#endif - -// ignore if not touching a PV leaf - if (ent != clent) // clent is ALLWAYS sent - { -// ignore ents without visible models - if (!ent->v.modelindex || !pr_strings[ent->v.model]) - continue; - - for (i=0 ; i < ent->num_leafs ; i++) - if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) )) - break; - - if (i == ent->num_leafs) - continue; // not visible - } - - if (msg->maxsize - msg->cursize < 16) - { - Con_Printf ("packet overflow\n"); - return; - } - -// send an update - bits = 0; - - for (i=0 ; i<3 ; i++) - { - miss = ent->v.origin[i] - ent->baseline.origin[i]; - if ( miss < -0.1 || miss > 0.1 ) - bits |= U_ORIGIN1<v.angles[0] != ent->baseline.angles[0] ) - bits |= U_ANGLE1; - - if ( ent->v.angles[1] != ent->baseline.angles[1] ) - bits |= U_ANGLE2; - - if ( ent->v.angles[2] != ent->baseline.angles[2] ) - bits |= U_ANGLE3; - - if (ent->v.movetype == MOVETYPE_STEP) - bits |= U_NOLERP; // don't mess up the step animation - - if (ent->baseline.colormap != ent->v.colormap) - bits |= U_COLORMAP; - - if (ent->baseline.skin != ent->v.skin) - bits |= U_SKIN; - - if (ent->baseline.frame != ent->v.frame) - bits |= U_FRAME; - - if (ent->baseline.effects != ent->v.effects) - bits |= U_EFFECTS; - - if (ent->baseline.modelindex != ent->v.modelindex) - bits |= U_MODEL; - - if (e >= 256) - bits |= U_LONGENTITY; - - if (bits >= 256) - bits |= U_MOREBITS; - - // - // write the message - // - MSG_WriteByte (msg,bits | U_SIGNAL); - - if (bits & U_MOREBITS) - MSG_WriteByte (msg, bits>>8); - if (bits & U_LONGENTITY) - MSG_WriteShort (msg,e); - else - MSG_WriteByte (msg,e); - - if (bits & U_MODEL) - MSG_WriteByte (msg, ent->v.modelindex); - if (bits & U_FRAME) - MSG_WriteByte (msg, ent->v.frame); - if (bits & U_COLORMAP) - MSG_WriteByte (msg, ent->v.colormap); - if (bits & U_SKIN) - MSG_WriteByte (msg, ent->v.skin); - if (bits & U_EFFECTS) - MSG_WriteByte (msg, ent->v.effects); - if (bits & U_ORIGIN1) - MSG_WriteCoord (msg, ent->v.origin[0]); - if (bits & U_ANGLE1) - MSG_WriteAngle(msg, ent->v.angles[0]); - if (bits & U_ORIGIN2) - MSG_WriteCoord (msg, ent->v.origin[1]); - if (bits & U_ANGLE2) - MSG_WriteAngle(msg, ent->v.angles[1]); - if (bits & U_ORIGIN3) - MSG_WriteCoord (msg, ent->v.origin[2]); - if (bits & U_ANGLE3) - MSG_WriteAngle(msg, ent->v.angles[2]); - } -} - -/* -============= -SV_CleanupEnts - -============= -*/ -void SV_CleanupEnts (void) -{ - int e; - edict_t *ent; - - ent = NEXT_EDICT(sv.edicts); - for (e=1 ; ev.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH; - } - -} - -/* -================== -SV_WriteClientdataToMessage - -================== -*/ -void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) -{ - int bits; - int i; - edict_t *other; - int items; -#ifndef QUAKE2 - eval_t *val; -#endif - -// -// send a damage message -// - if (ent->v.dmg_take || ent->v.dmg_save) - { - other = PROG_TO_EDICT(ent->v.dmg_inflictor); - MSG_WriteByte (msg, svc_damage); - MSG_WriteByte (msg, ent->v.dmg_save); - MSG_WriteByte (msg, ent->v.dmg_take); - for (i=0 ; i<3 ; i++) - MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i])); - - ent->v.dmg_take = 0; - ent->v.dmg_save = 0; - } - -// -// send the current viewpos offset from the view entity -// - SV_SetIdealPitch (); // how much to look up / down ideally - -// a fixangle might get lost in a dropped packet. Oh well. - if ( ent->v.fixangle ) - { - MSG_WriteByte (msg, svc_setangle); - for (i=0 ; i < 3 ; i++) - MSG_WriteAngle (msg, ent->v.angles[i] ); - ent->v.fixangle = 0; - } - - bits = 0; - - if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT) - bits |= SU_VIEWHEIGHT; - - if (ent->v.idealpitch) - bits |= SU_IDEALPITCH; - -// stuff the sigil bits into the high bits of items for sbar, or else -// mix in items2 -#ifdef QUAKE2 - items = (int)ent->v.items | ((int)ent->v.items2 << 23); -#else - val = GetEdictFieldValue(ent, "items2"); - - if (val) - items = (int)ent->v.items | ((int)val->_float << 23); - else - items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28); -#endif - - bits |= SU_ITEMS; - - if ( (int)ent->v.flags & FL_ONGROUND) - bits |= SU_ONGROUND; - - if ( ent->v.waterlevel >= 2) - bits |= SU_INWATER; - - for (i=0 ; i<3 ; i++) - { - if (ent->v.punchangle[i]) - bits |= (SU_PUNCH1<v.velocity[i]) - bits |= (SU_VELOCITY1<v.weaponframe) - bits |= SU_WEAPONFRAME; - - if (ent->v.armorvalue) - bits |= SU_ARMOR; - -// if (ent->v.weapon) - bits |= SU_WEAPON; - -// send the data - - MSG_WriteByte (msg, svc_clientdata); - MSG_WriteShort (msg, bits); - - if (bits & SU_VIEWHEIGHT) - MSG_WriteChar (msg, ent->v.view_ofs[2]); - - if (bits & SU_IDEALPITCH) - MSG_WriteChar (msg, ent->v.idealpitch); - - for (i=0 ; i<3 ; i++) - { - if (bits & (SU_PUNCH1<v.punchangle[i]); - if (bits & (SU_VELOCITY1<v.velocity[i]/16); - } - -// [always sent] if (bits & SU_ITEMS) - MSG_WriteLong (msg, items); - - if (bits & SU_WEAPONFRAME) - MSG_WriteByte (msg, ent->v.weaponframe); - if (bits & SU_ARMOR) - MSG_WriteByte (msg, ent->v.armorvalue); - if (bits & SU_WEAPON) - MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel)); - - MSG_WriteShort (msg, ent->v.health); - MSG_WriteByte (msg, ent->v.currentammo); - MSG_WriteByte (msg, ent->v.ammo_shells); - MSG_WriteByte (msg, ent->v.ammo_nails); - MSG_WriteByte (msg, ent->v.ammo_rockets); - MSG_WriteByte (msg, ent->v.ammo_cells); - - if (standard_quake) - { - MSG_WriteByte (msg, ent->v.weapon); - } - else - { - for(i=0;i<32;i++) - { - if ( ((int)ent->v.weapon) & (1<edict, &msg); - - SV_WriteEntitiesToClient (client->edict, &msg); - -// copy the server datagram if there is space - if (msg.cursize + sv.datagram.cursize < msg.maxsize) - SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize); - -// send the datagram - if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) - { - SV_DropClient (true);// if the message couldn't send, kick off - return false; - } - - return true; -} - -/* -======================= -SV_UpdateToReliableMessages -======================= -*/ -void SV_UpdateToReliableMessages (void) -{ - int i, j; - client_t *client; - -// check for changes to be sent over the reliable streams - for (i=0, host_client = svs.clients ; iold_frags != host_client->edict->v.frags) - { - for (j=0, client = svs.clients ; jactive) - continue; - MSG_WriteByte (&client->message, svc_updatefrags); - MSG_WriteByte (&client->message, i); - MSG_WriteShort (&client->message, host_client->edict->v.frags); - } - - host_client->old_frags = host_client->edict->v.frags; - } - } - - for (j=0, client = svs.clients ; jactive) - continue; - SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); - } - - SZ_Clear (&sv.reliable_datagram); -} - - -/* -======================= -SV_SendNop - -Send a nop message without trashing or sending the accumulated client -message buffer -======================= -*/ -void SV_SendNop (client_t *client) -{ - sizebuf_t msg; - byte buf[4]; - - msg.data = buf; - msg.maxsize = sizeof(buf); - msg.cursize = 0; - - MSG_WriteChar (&msg, svc_nop); - - if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) - SV_DropClient (true); // if the message couldn't send, kick off - client->last_message = realtime; -} - -/* -======================= -SV_SendClientMessages -======================= -*/ -void SV_SendClientMessages (void) -{ - int i; - -// update frags, names, etc - SV_UpdateToReliableMessages (); - -// build individual updates - for (i=0, host_client = svs.clients ; iactive) - continue; - - if (host_client->spawned) - { - if (!SV_SendClientDatagram (host_client)) - continue; - } - else - { - // the player isn't totally in the game yet - // send small keepalive messages if too much time has passed - // send a full message when the next signon stage has been requested - // some other message data (name changes, etc) may accumulate - // between signon stages - if (!host_client->sendsignon) - { - if (realtime - host_client->last_message > 5) - SV_SendNop (host_client); - continue; // don't send out non-signon messages - } - } - - // check for an overflowed message. Should only happen - // on a very fucked up connection that backs up a lot, then - // changes level - if (host_client->message.overflowed) - { - SV_DropClient (true); - host_client->message.overflowed = false; - continue; - } - - if (host_client->message.cursize || host_client->dropasap) - { - if (!NET_CanSendMessage (host_client->netconnection)) - { -// I_Printf ("can't write\n"); - continue; - } - - if (host_client->dropasap) - SV_DropClient (false); // went to another level - else - { - if (NET_SendMessage (host_client->netconnection - , &host_client->message) == -1) - SV_DropClient (true); // if the message couldn't send, kick off - SZ_Clear (&host_client->message); - host_client->last_message = realtime; - host_client->sendsignon = false; - } - } - } - - -// clear muzzle flashes - SV_CleanupEnts (); -} - - -/* -============================================================================== - -SERVER SPAWNING - -============================================================================== -*/ - -/* -================ -SV_ModelIndex - -================ -*/ -int SV_ModelIndex (char *name) -{ - int i; - - if (!name || !name[0]) - return 0; - - for (i=0 ; ifree) - continue; - if (entnum > svs.maxclients && !svent->v.modelindex) - continue; - - // - // create entity baseline - // - VectorCopy (svent->v.origin, svent->baseline.origin); - VectorCopy (svent->v.angles, svent->baseline.angles); - svent->baseline.frame = svent->v.frame; - svent->baseline.skin = svent->v.skin; - if (entnum > 0 && entnum <= svs.maxclients) - { - svent->baseline.colormap = entnum; - svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl"); - } - else - { - svent->baseline.colormap = 0; - svent->baseline.modelindex = - SV_ModelIndex(pr_strings + svent->v.model); - } - - // - // add to the message - // - MSG_WriteByte (&sv.signon,svc_spawnbaseline); - MSG_WriteShort (&sv.signon,entnum); - - MSG_WriteByte (&sv.signon, svent->baseline.modelindex); - MSG_WriteByte (&sv.signon, svent->baseline.frame); - MSG_WriteByte (&sv.signon, svent->baseline.colormap); - MSG_WriteByte (&sv.signon, svent->baseline.skin); - for (i=0 ; i<3 ; i++) - { - MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]); - MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]); - } - } -} - - -/* -================ -SV_SendReconnect - -Tell all the clients that the server is changing levels -================ -*/ -void SV_SendReconnect (void) -{ - char data[128]; - sizebuf_t msg; - - msg.data = data; - msg.cursize = 0; - msg.maxsize = sizeof(data); - - MSG_WriteChar (&msg, svc_stufftext); - MSG_WriteString (&msg, "reconnect\n"); - NET_SendToAll (&msg, 5); - - if (cls.state != ca_dedicated) -#ifdef QUAKE2 - Cbuf_InsertText ("reconnect\n"); -#else - Cmd_ExecuteString ("reconnect\n", src_command); -#endif -} - - -/* -================ -SV_SaveSpawnparms - -Grabs the current state of each client for saving across the -transition to another level -================ -*/ -void SV_SaveSpawnparms (void) -{ - int i, j; - - svs.serverflags = pr_global_struct->serverflags; - - for (i=0, host_client = svs.clients ; iactive) - continue; - - // call the progs to get default spawn parms for the new client - pr_global_struct->self = EDICT_TO_PROG(host_client->edict); - PR_ExecuteProgram (pr_global_struct->SetChangeParms); - for (j=0 ; jspawn_parms[j] = (&pr_global_struct->parm1)[j]; - } -} - - -/* -================ -SV_SpawnServer - -This is called at the start of each level -================ -*/ -extern float scr_centertime_off; - -#ifdef QUAKE2 -void SV_SpawnServer (char *server, char *startspot) -#else -void SV_SpawnServer (char *server) -#endif -{ - edict_t *ent; - int i; - - // let's not have any servers with no name - if (hostname.string[0] == 0) - Cvar_Set ("hostname", "UNNAMED"); - scr_centertime_off = 0; - - Con_DPrintf ("SpawnServer: %s\n",server); - svs.changelevel_issued = false; // now safe to issue another - -// -// tell all connected clients that we are going to a new level -// - if (sv.active) - { - SV_SendReconnect (); - } - -// -// make cvars consistant -// - if (coop.value) - Cvar_SetValue ("deathmatch", 0); - current_skill = (int)(skill.value + 0.5); - if (current_skill < 0) - current_skill = 0; - if (current_skill > 3) - current_skill = 3; - - Cvar_SetValue ("skill", (float)current_skill); - -// -// set up the new server -// - Host_ClearMemory (); - - memset (&sv, 0, sizeof(sv)); - - strcpy (sv.name, server); -#ifdef QUAKE2 - if (startspot) - strcpy(sv.startspot, startspot); -#endif - -// load progs to get entity field count - PR_LoadProgs (); - -// allocate server memory - sv.max_edicts = MAX_EDICTS; - - sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts"); - - sv.datagram.maxsize = sizeof(sv.datagram_buf); - sv.datagram.cursize = 0; - sv.datagram.data = sv.datagram_buf; - - sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf); - sv.reliable_datagram.cursize = 0; - sv.reliable_datagram.data = sv.reliable_datagram_buf; - - sv.signon.maxsize = sizeof(sv.signon_buf); - sv.signon.cursize = 0; - sv.signon.data = sv.signon_buf; - -// leave slots at start for clients only - sv.num_edicts = svs.maxclients+1; - for (i=0 ; inumsubmodels ; i++) - { - sv.model_precache[1+i] = localmodels[i]; - sv.models[i+1] = Mod_ForName (localmodels[i], false); - } - -// -// load the rest of the entities -// - ent = EDICT_NUM(0); - memset (&ent->v, 0, progs->entityfields * 4); - ent->free = false; - ent->v.model = sv.worldmodel->name - pr_strings; - ent->v.modelindex = 1; // world model - ent->v.solid = SOLID_BSP; - ent->v.movetype = MOVETYPE_PUSH; - - if (coop.value) - pr_global_struct->coop = coop.value; - else - pr_global_struct->deathmatch = deathmatch.value; - - pr_global_struct->mapname = sv.name - pr_strings; -#ifdef QUAKE2 - pr_global_struct->startspot = sv.startspot - pr_strings; -#endif - -// serverflags are for cross level information (sigils) - pr_global_struct->serverflags = svs.serverflags; - - ED_LoadFromFile (sv.worldmodel->entities); - - sv.active = true; - -// all setup is completed, any further precache statements are errors - sv.state = ss_active; - -// run two frames to allow everything to settle - host_frametime = 0.1; - SV_Physics (); - SV_Physics (); - -// create a baseline for more efficient communications - SV_CreateBaseline (); - -// send serverinfo to all connected clients - for (i=0,host_client = svs.clients ; iactive) - SV_SendServerinfo (host_client); - - Con_DPrintf ("Server spawned.\n"); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_main.c -- server main program + +#include "quakedef.h" + +server_t sv; +server_static_t svs; + +char localmodels[MAX_MODELS][5]; // inline model names for precache + +//============================================================================ + +/* +=============== +SV_Init +=============== +*/ +void SV_Init (void) +{ + int i; + extern cvar_t sv_maxvelocity; + extern cvar_t sv_gravity; + extern cvar_t sv_nostep; + extern cvar_t sv_friction; + extern cvar_t sv_edgefriction; + extern cvar_t sv_stopspeed; + extern cvar_t sv_maxspeed; + extern cvar_t sv_accelerate; + extern cvar_t sv_idealpitchscale; + extern cvar_t sv_aim; + + Cvar_RegisterVariable (&sv_maxvelocity); + Cvar_RegisterVariable (&sv_gravity); + Cvar_RegisterVariable (&sv_friction); + Cvar_RegisterVariable (&sv_edgefriction); + Cvar_RegisterVariable (&sv_stopspeed); + Cvar_RegisterVariable (&sv_maxspeed); + Cvar_RegisterVariable (&sv_accelerate); + Cvar_RegisterVariable (&sv_idealpitchscale); + Cvar_RegisterVariable (&sv_aim); + Cvar_RegisterVariable (&sv_nostep); + + for (i=0 ; i MAX_DATAGRAM-16) + return; + MSG_WriteByte (&sv.datagram, svc_particle); + MSG_WriteCoord (&sv.datagram, org[0]); + MSG_WriteCoord (&sv.datagram, org[1]); + MSG_WriteCoord (&sv.datagram, org[2]); + for (i=0 ; i<3 ; i++) + { + v = dir[i]*16; + if (v > 127) + v = 127; + else if (v < -128) + v = -128; + MSG_WriteChar (&sv.datagram, v); + } + MSG_WriteByte (&sv.datagram, count); + MSG_WriteByte (&sv.datagram, color); +} + +/* +================== +SV_StartSound + +Each entity can have eight independant sound sources, like voice, +weapon, feet, etc. + +Channel 0 is an auto-allocate channel, the others override anything +allready running on that entity/channel pair. + +An attenuation of 0 will play full volume everywhere in the level. +Larger attenuations will drop off. (max 4 attenuation) + +================== +*/ +void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, + float attenuation) +{ + int sound_num; + int field_mask; + int i; + int ent; + + if (volume < 0 || volume > 255) + Sys_Error ("SV_StartSound: volume = %i", volume); + + if (attenuation < 0 || attenuation > 4) + Sys_Error ("SV_StartSound: attenuation = %f", attenuation); + + if (channel < 0 || channel > 7) + Sys_Error ("SV_StartSound: channel = %i", channel); + + if (sv.datagram.cursize > MAX_DATAGRAM-16) + return; + +// find precache number for sound + for (sound_num=1 ; sound_numv.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i])); +} + +/* +============================================================================== + +CLIENT SPAWNING + +============================================================================== +*/ + +/* +================ +SV_SendServerinfo + +Sends the first message from the server to a connected client. +This will be sent on the initial connection and upon each server load. +================ +*/ +void SV_SendServerinfo (client_t *client) +{ + char **s; + char message[2048]; + + MSG_WriteByte (&client->message, svc_print); + sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc); + MSG_WriteString (&client->message,message); + + MSG_WriteByte (&client->message, svc_serverinfo); + MSG_WriteLong (&client->message, PROTOCOL_VERSION); + MSG_WriteByte (&client->message, svs.maxclients); + + if (!coop.value && deathmatch.value) + MSG_WriteByte (&client->message, GAME_DEATHMATCH); + else + MSG_WriteByte (&client->message, GAME_COOP); + + sprintf (message, pr_strings+sv.edicts->v.message); + + MSG_WriteString (&client->message,message); + + for (s = sv.model_precache+1 ; *s ; s++) + MSG_WriteString (&client->message, *s); + MSG_WriteByte (&client->message, 0); + + for (s = sv.sound_precache+1 ; *s ; s++) + MSG_WriteString (&client->message, *s); + MSG_WriteByte (&client->message, 0); + +// send music + MSG_WriteByte (&client->message, svc_cdtrack); + MSG_WriteByte (&client->message, sv.edicts->v.sounds); + MSG_WriteByte (&client->message, sv.edicts->v.sounds); + +// set view + MSG_WriteByte (&client->message, svc_setview); + MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict)); + + MSG_WriteByte (&client->message, svc_signonnum); + MSG_WriteByte (&client->message, 1); + + client->sendsignon = true; + client->spawned = false; // need prespawn, spawn, etc +} + +/* +================ +SV_ConnectClient + +Initializes a client_t for a new net connection. This will only be called +once for a player each game, not once for each level change. +================ +*/ +void SV_ConnectClient (int clientnum) +{ + edict_t *ent; + client_t *client; + int edictnum; + struct qsocket_s *netconnection; + int i; + float spawn_parms[NUM_SPAWN_PARMS]; + + client = svs.clients + clientnum; + + Con_DPrintf ("Client %s connected\n", client->netconnection->address); + + edictnum = clientnum+1; + + ent = EDICT_NUM(edictnum); + +// set up the client_t + netconnection = client->netconnection; + + if (sv.loadgame) + memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms)); + memset (client, 0, sizeof(*client)); + client->netconnection = netconnection; + + strcpy (client->name, "unconnected"); + client->active = true; + client->spawned = false; + client->edict = ent; + client->message.data = client->msgbuf; + client->message.maxsize = sizeof(client->msgbuf); + client->message.allowoverflow = true; // we can catch it + +#ifdef IDGODS + client->privileged = IsID(&client->netconnection->addr); +#else + client->privileged = false; +#endif + + if (sv.loadgame) + memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms)); + else + { + // call the progs to get default spawn parms for the new client + PR_ExecuteProgram (pr_global_struct->SetNewParms); + for (i=0 ; ispawn_parms[i] = (&pr_global_struct->parm1)[i]; + } + + SV_SendServerinfo (client); +} + + +/* +=================== +SV_CheckForNewClients + +=================== +*/ +void SV_CheckForNewClients (void) +{ + struct qsocket_s *ret; + int i; + +// +// check for new connections +// + while (1) + { + ret = NET_CheckNewConnections (); + if (!ret) + break; + + // + // init a new client structure + // + for (i=0 ; icontents < 0) + { + if (node->contents != CONTENTS_SOLID) + { + pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel); + for (i=0 ; iplane; + d = DotProduct (org, plane->normal) - plane->dist; + if (d > 8) + node = node->children[0]; + else if (d < -8) + node = node->children[1]; + else + { // go down both + SV_AddToFatPVS (org, node->children[0]); + node = node->children[1]; + } + } +} + +/* +============= +SV_FatPVS + +Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the +given point. +============= +*/ +byte *SV_FatPVS (vec3_t org) +{ + fatbytes = (sv.worldmodel->numleafs+31)>>3; + Q_memset (fatpvs, 0, fatbytes); + SV_AddToFatPVS (org, sv.worldmodel->nodes); + return fatpvs; +} + +//============================================================================= + + +/* +============= +SV_WriteEntitiesToClient + +============= +*/ +void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) +{ + int e, i; + int bits; + byte *pvs; + vec3_t org; + float miss; + edict_t *ent; + +// find the client's PVS + VectorAdd (clent->v.origin, clent->v.view_ofs, org); + pvs = SV_FatPVS (org); + +// send over all entities (excpet the client) that touch the pvs + ent = NEXT_EDICT(sv.edicts); + for (e=1 ; ev.effects == EF_NODRAW) + continue; +#endif + +// ignore if not touching a PV leaf + if (ent != clent) // clent is ALLWAYS sent + { +// ignore ents without visible models + if (!ent->v.modelindex || !pr_strings[ent->v.model]) + continue; + + for (i=0 ; i < ent->num_leafs ; i++) + if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) )) + break; + + if (i == ent->num_leafs) + continue; // not visible + } + + if (msg->maxsize - msg->cursize < 16) + { + Con_Printf ("packet overflow\n"); + return; + } + +// send an update + bits = 0; + + for (i=0 ; i<3 ; i++) + { + miss = ent->v.origin[i] - ent->baseline.origin[i]; + if ( miss < -0.1 || miss > 0.1 ) + bits |= U_ORIGIN1<v.angles[0] != ent->baseline.angles[0] ) + bits |= U_ANGLE1; + + if ( ent->v.angles[1] != ent->baseline.angles[1] ) + bits |= U_ANGLE2; + + if ( ent->v.angles[2] != ent->baseline.angles[2] ) + bits |= U_ANGLE3; + + if (ent->v.movetype == MOVETYPE_STEP) + bits |= U_NOLERP; // don't mess up the step animation + + if (ent->baseline.colormap != ent->v.colormap) + bits |= U_COLORMAP; + + if (ent->baseline.skin != ent->v.skin) + bits |= U_SKIN; + + if (ent->baseline.frame != ent->v.frame) + bits |= U_FRAME; + + if (ent->baseline.effects != ent->v.effects) + bits |= U_EFFECTS; + + if (ent->baseline.modelindex != ent->v.modelindex) + bits |= U_MODEL; + + if (e >= 256) + bits |= U_LONGENTITY; + + if (bits >= 256) + bits |= U_MOREBITS; + + // + // write the message + // + MSG_WriteByte (msg,bits | U_SIGNAL); + + if (bits & U_MOREBITS) + MSG_WriteByte (msg, bits>>8); + if (bits & U_LONGENTITY) + MSG_WriteShort (msg,e); + else + MSG_WriteByte (msg,e); + + if (bits & U_MODEL) + MSG_WriteByte (msg, ent->v.modelindex); + if (bits & U_FRAME) + MSG_WriteByte (msg, ent->v.frame); + if (bits & U_COLORMAP) + MSG_WriteByte (msg, ent->v.colormap); + if (bits & U_SKIN) + MSG_WriteByte (msg, ent->v.skin); + if (bits & U_EFFECTS) + MSG_WriteByte (msg, ent->v.effects); + if (bits & U_ORIGIN1) + MSG_WriteCoord (msg, ent->v.origin[0]); + if (bits & U_ANGLE1) + MSG_WriteAngle(msg, ent->v.angles[0]); + if (bits & U_ORIGIN2) + MSG_WriteCoord (msg, ent->v.origin[1]); + if (bits & U_ANGLE2) + MSG_WriteAngle(msg, ent->v.angles[1]); + if (bits & U_ORIGIN3) + MSG_WriteCoord (msg, ent->v.origin[2]); + if (bits & U_ANGLE3) + MSG_WriteAngle(msg, ent->v.angles[2]); + } +} + +/* +============= +SV_CleanupEnts + +============= +*/ +void SV_CleanupEnts (void) +{ + int e; + edict_t *ent; + + ent = NEXT_EDICT(sv.edicts); + for (e=1 ; ev.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH; + } + +} + +/* +================== +SV_WriteClientdataToMessage + +================== +*/ +void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) +{ + int bits; + int i; + edict_t *other; + int items; +#ifndef QUAKE2 + eval_t *val; +#endif + +// +// send a damage message +// + if (ent->v.dmg_take || ent->v.dmg_save) + { + other = PROG_TO_EDICT(ent->v.dmg_inflictor); + MSG_WriteByte (msg, svc_damage); + MSG_WriteByte (msg, ent->v.dmg_save); + MSG_WriteByte (msg, ent->v.dmg_take); + for (i=0 ; i<3 ; i++) + MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i])); + + ent->v.dmg_take = 0; + ent->v.dmg_save = 0; + } + +// +// send the current viewpos offset from the view entity +// + SV_SetIdealPitch (); // how much to look up / down ideally + +// a fixangle might get lost in a dropped packet. Oh well. + if ( ent->v.fixangle ) + { + MSG_WriteByte (msg, svc_setangle); + for (i=0 ; i < 3 ; i++) + MSG_WriteAngle (msg, ent->v.angles[i] ); + ent->v.fixangle = 0; + } + + bits = 0; + + if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT) + bits |= SU_VIEWHEIGHT; + + if (ent->v.idealpitch) + bits |= SU_IDEALPITCH; + +// stuff the sigil bits into the high bits of items for sbar, or else +// mix in items2 +#ifdef QUAKE2 + items = (int)ent->v.items | ((int)ent->v.items2 << 23); +#else + val = GetEdictFieldValue(ent, "items2"); + + if (val) + items = (int)ent->v.items | ((int)val->_float << 23); + else + items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28); +#endif + + bits |= SU_ITEMS; + + if ( (int)ent->v.flags & FL_ONGROUND) + bits |= SU_ONGROUND; + + if ( ent->v.waterlevel >= 2) + bits |= SU_INWATER; + + for (i=0 ; i<3 ; i++) + { + if (ent->v.punchangle[i]) + bits |= (SU_PUNCH1<v.velocity[i]) + bits |= (SU_VELOCITY1<v.weaponframe) + bits |= SU_WEAPONFRAME; + + if (ent->v.armorvalue) + bits |= SU_ARMOR; + +// if (ent->v.weapon) + bits |= SU_WEAPON; + +// send the data + + MSG_WriteByte (msg, svc_clientdata); + MSG_WriteShort (msg, bits); + + if (bits & SU_VIEWHEIGHT) + MSG_WriteChar (msg, ent->v.view_ofs[2]); + + if (bits & SU_IDEALPITCH) + MSG_WriteChar (msg, ent->v.idealpitch); + + for (i=0 ; i<3 ; i++) + { + if (bits & (SU_PUNCH1<v.punchangle[i]); + if (bits & (SU_VELOCITY1<v.velocity[i]/16); + } + +// [always sent] if (bits & SU_ITEMS) + MSG_WriteLong (msg, items); + + if (bits & SU_WEAPONFRAME) + MSG_WriteByte (msg, ent->v.weaponframe); + if (bits & SU_ARMOR) + MSG_WriteByte (msg, ent->v.armorvalue); + if (bits & SU_WEAPON) + MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel)); + + MSG_WriteShort (msg, ent->v.health); + MSG_WriteByte (msg, ent->v.currentammo); + MSG_WriteByte (msg, ent->v.ammo_shells); + MSG_WriteByte (msg, ent->v.ammo_nails); + MSG_WriteByte (msg, ent->v.ammo_rockets); + MSG_WriteByte (msg, ent->v.ammo_cells); + + if (standard_quake) + { + MSG_WriteByte (msg, ent->v.weapon); + } + else + { + for(i=0;i<32;i++) + { + if ( ((int)ent->v.weapon) & (1<edict, &msg); + + SV_WriteEntitiesToClient (client->edict, &msg); + +// copy the server datagram if there is space + if (msg.cursize + sv.datagram.cursize < msg.maxsize) + SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize); + +// send the datagram + if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) + { + SV_DropClient (true);// if the message couldn't send, kick off + return false; + } + + return true; +} + +/* +======================= +SV_UpdateToReliableMessages +======================= +*/ +void SV_UpdateToReliableMessages (void) +{ + int i, j; + client_t *client; + +// check for changes to be sent over the reliable streams + for (i=0, host_client = svs.clients ; iold_frags != host_client->edict->v.frags) + { + for (j=0, client = svs.clients ; jactive) + continue; + MSG_WriteByte (&client->message, svc_updatefrags); + MSG_WriteByte (&client->message, i); + MSG_WriteShort (&client->message, host_client->edict->v.frags); + } + + host_client->old_frags = host_client->edict->v.frags; + } + } + + for (j=0, client = svs.clients ; jactive) + continue; + SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); + } + + SZ_Clear (&sv.reliable_datagram); +} + + +/* +======================= +SV_SendNop + +Send a nop message without trashing or sending the accumulated client +message buffer +======================= +*/ +void SV_SendNop (client_t *client) +{ + sizebuf_t msg; + byte buf[4]; + + msg.data = buf; + msg.maxsize = sizeof(buf); + msg.cursize = 0; + + MSG_WriteChar (&msg, svc_nop); + + if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) + SV_DropClient (true); // if the message couldn't send, kick off + client->last_message = realtime; +} + +/* +======================= +SV_SendClientMessages +======================= +*/ +void SV_SendClientMessages (void) +{ + int i; + +// update frags, names, etc + SV_UpdateToReliableMessages (); + +// build individual updates + for (i=0, host_client = svs.clients ; iactive) + continue; + + if (host_client->spawned) + { + if (!SV_SendClientDatagram (host_client)) + continue; + } + else + { + // the player isn't totally in the game yet + // send small keepalive messages if too much time has passed + // send a full message when the next signon stage has been requested + // some other message data (name changes, etc) may accumulate + // between signon stages + if (!host_client->sendsignon) + { + if (realtime - host_client->last_message > 5) + SV_SendNop (host_client); + continue; // don't send out non-signon messages + } + } + + // check for an overflowed message. Should only happen + // on a very fucked up connection that backs up a lot, then + // changes level + if (host_client->message.overflowed) + { + SV_DropClient (true); + host_client->message.overflowed = false; + continue; + } + + if (host_client->message.cursize || host_client->dropasap) + { + if (!NET_CanSendMessage (host_client->netconnection)) + { +// I_Printf ("can't write\n"); + continue; + } + + if (host_client->dropasap) + SV_DropClient (false); // went to another level + else + { + if (NET_SendMessage (host_client->netconnection + , &host_client->message) == -1) + SV_DropClient (true); // if the message couldn't send, kick off + SZ_Clear (&host_client->message); + host_client->last_message = realtime; + host_client->sendsignon = false; + } + } + } + + +// clear muzzle flashes + SV_CleanupEnts (); +} + + +/* +============================================================================== + +SERVER SPAWNING + +============================================================================== +*/ + +/* +================ +SV_ModelIndex + +================ +*/ +int SV_ModelIndex (char *name) +{ + int i; + + if (!name || !name[0]) + return 0; + + for (i=0 ; ifree) + continue; + if (entnum > svs.maxclients && !svent->v.modelindex) + continue; + + // + // create entity baseline + // + VectorCopy (svent->v.origin, svent->baseline.origin); + VectorCopy (svent->v.angles, svent->baseline.angles); + svent->baseline.frame = svent->v.frame; + svent->baseline.skin = svent->v.skin; + if (entnum > 0 && entnum <= svs.maxclients) + { + svent->baseline.colormap = entnum; + svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl"); + } + else + { + svent->baseline.colormap = 0; + svent->baseline.modelindex = + SV_ModelIndex(pr_strings + svent->v.model); + } + + // + // add to the message + // + MSG_WriteByte (&sv.signon,svc_spawnbaseline); + MSG_WriteShort (&sv.signon,entnum); + + MSG_WriteByte (&sv.signon, svent->baseline.modelindex); + MSG_WriteByte (&sv.signon, svent->baseline.frame); + MSG_WriteByte (&sv.signon, svent->baseline.colormap); + MSG_WriteByte (&sv.signon, svent->baseline.skin); + for (i=0 ; i<3 ; i++) + { + MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]); + MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]); + } + } +} + + +/* +================ +SV_SendReconnect + +Tell all the clients that the server is changing levels +================ +*/ +void SV_SendReconnect (void) +{ + char data[128]; + sizebuf_t msg; + + msg.data = data; + msg.cursize = 0; + msg.maxsize = sizeof(data); + + MSG_WriteChar (&msg, svc_stufftext); + MSG_WriteString (&msg, "reconnect\n"); + NET_SendToAll (&msg, 5); + + if (cls.state != ca_dedicated) +#ifdef QUAKE2 + Cbuf_InsertText ("reconnect\n"); +#else + Cmd_ExecuteString ("reconnect\n", src_command); +#endif +} + + +/* +================ +SV_SaveSpawnparms + +Grabs the current state of each client for saving across the +transition to another level +================ +*/ +void SV_SaveSpawnparms (void) +{ + int i, j; + + svs.serverflags = pr_global_struct->serverflags; + + for (i=0, host_client = svs.clients ; iactive) + continue; + + // call the progs to get default spawn parms for the new client + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); + PR_ExecuteProgram (pr_global_struct->SetChangeParms); + for (j=0 ; jspawn_parms[j] = (&pr_global_struct->parm1)[j]; + } +} + + +/* +================ +SV_SpawnServer + +This is called at the start of each level +================ +*/ +extern float scr_centertime_off; + +#ifdef QUAKE2 +void SV_SpawnServer (char *server, char *startspot) +#else +void SV_SpawnServer (char *server) +#endif +{ + edict_t *ent; + int i; + + // let's not have any servers with no name + if (hostname.string[0] == 0) + Cvar_Set ("hostname", "UNNAMED"); + scr_centertime_off = 0; + + Con_DPrintf ("SpawnServer: %s\n",server); + svs.changelevel_issued = false; // now safe to issue another + +// +// tell all connected clients that we are going to a new level +// + if (sv.active) + { + SV_SendReconnect (); + } + +// +// make cvars consistant +// + if (coop.value) + Cvar_SetValue ("deathmatch", 0); + current_skill = (int)(skill.value + 0.5); + if (current_skill < 0) + current_skill = 0; + if (current_skill > 3) + current_skill = 3; + + Cvar_SetValue ("skill", (float)current_skill); + +// +// set up the new server +// + Host_ClearMemory (); + + memset (&sv, 0, sizeof(sv)); + + strcpy (sv.name, server); +#ifdef QUAKE2 + if (startspot) + strcpy(sv.startspot, startspot); +#endif + +// load progs to get entity field count + PR_LoadProgs (); + +// allocate server memory + sv.max_edicts = MAX_EDICTS; + + sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts"); + + sv.datagram.maxsize = sizeof(sv.datagram_buf); + sv.datagram.cursize = 0; + sv.datagram.data = sv.datagram_buf; + + sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf); + sv.reliable_datagram.cursize = 0; + sv.reliable_datagram.data = sv.reliable_datagram_buf; + + sv.signon.maxsize = sizeof(sv.signon_buf); + sv.signon.cursize = 0; + sv.signon.data = sv.signon_buf; + +// leave slots at start for clients only + sv.num_edicts = svs.maxclients+1; + for (i=0 ; inumsubmodels ; i++) + { + sv.model_precache[1+i] = localmodels[i]; + sv.models[i+1] = Mod_ForName (localmodels[i], false); + } + +// +// load the rest of the entities +// + ent = EDICT_NUM(0); + memset (&ent->v, 0, progs->entityfields * 4); + ent->free = false; + ent->v.model = sv.worldmodel->name - pr_strings; + ent->v.modelindex = 1; // world model + ent->v.solid = SOLID_BSP; + ent->v.movetype = MOVETYPE_PUSH; + + if (coop.value) + pr_global_struct->coop = coop.value; + else + pr_global_struct->deathmatch = deathmatch.value; + + pr_global_struct->mapname = sv.name - pr_strings; +#ifdef QUAKE2 + pr_global_struct->startspot = sv.startspot - pr_strings; +#endif + +// serverflags are for cross level information (sigils) + pr_global_struct->serverflags = svs.serverflags; + + ED_LoadFromFile (sv.worldmodel->entities); + + sv.active = true; + +// all setup is completed, any further precache statements are errors + sv.state = ss_active; + +// run two frames to allow everything to settle + host_frametime = 0.1; + SV_Physics (); + SV_Physics (); + +// create a baseline for more efficient communications + SV_CreateBaseline (); + +// send serverinfo to all connected clients + for (i=0,host_client = svs.clients ; iactive) + SV_SendServerinfo (host_client); + + Con_DPrintf ("Server spawned.\n"); +} + diff --git a/WinQuake/sv_move.c b/WinQuake/sv_move.c index a0078b9..fd967f9 100644 --- a/WinQuake/sv_move.c +++ b/WinQuake/sv_move.c @@ -1,427 +1,427 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_move.c -- monster movement - -#include "quakedef.h" - -#define STEPSIZE 18 - -/* -============= -SV_CheckBottom - -Returns false if any part of the bottom of the entity is off an edge that -is not a staircase. - -============= -*/ -int c_yes, c_no; - -qboolean SV_CheckBottom (edict_t *ent) -{ - vec3_t mins, maxs, start, stop; - trace_t trace; - int x, y; - float mid, bottom; - - VectorAdd (ent->v.origin, ent->v.mins, mins); - VectorAdd (ent->v.origin, ent->v.maxs, maxs); - -// if all of the points under the corners are solid world, don't bother -// with the tougher checks -// the corners must be within 16 of the midpoint - start[2] = mins[2] - 1; - for (x=0 ; x<=1 ; x++) - for (y=0 ; y<=1 ; y++) - { - start[0] = x ? maxs[0] : mins[0]; - start[1] = y ? maxs[1] : mins[1]; - if (SV_PointContents (start) != CONTENTS_SOLID) - goto realcheck; - } - - c_yes++; - return true; // we got out easy - -realcheck: - c_no++; -// -// check it for real... -// - start[2] = mins[2]; - -// the midpoint must be within 16 of the bottom - start[0] = stop[0] = (mins[0] + maxs[0])*0.5; - start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*STEPSIZE; - trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent); - - if (trace.fraction == 1.0) - return false; - mid = bottom = trace.endpos[2]; - -// the corners must be within 16 of the midpoint - for (x=0 ; x<=1 ; x++) - for (y=0 ; y<=1 ; y++) - { - start[0] = stop[0] = x ? maxs[0] : mins[0]; - start[1] = stop[1] = y ? maxs[1] : mins[1]; - - trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent); - - if (trace.fraction != 1.0 && trace.endpos[2] > bottom) - bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) - return false; - } - - c_yes++; - return true; -} - - -/* -============= -SV_movestep - -Called by monster program code. -The move will be adjusted for slopes and stairs, but if the move isn't -possible, no move is done, false is returned, and -pr_global_struct->trace_normal is set to the normal of the blocking wall -============= -*/ -qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) -{ - float dz; - vec3_t oldorg, neworg, end; - trace_t trace; - int i; - edict_t *enemy; - -// try the move - VectorCopy (ent->v.origin, oldorg); - VectorAdd (ent->v.origin, move, neworg); - -// flying monsters don't step up - if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) ) - { - // try one move with vertical motion, then one without - for (i=0 ; i<2 ; i++) - { - VectorAdd (ent->v.origin, move, neworg); - enemy = PROG_TO_EDICT(ent->v.enemy); - if (i == 0 && enemy != sv.edicts) - { - dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2]; - if (dz > 40) - neworg[2] -= 8; - if (dz < 30) - neworg[2] += 8; - } - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent); - - if (trace.fraction == 1) - { - if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY ) - return false; // swim monster left water - - VectorCopy (trace.endpos, ent->v.origin); - if (relink) - SV_LinkEdict (ent, true); - return true; - } - - if (enemy == sv.edicts) - break; - } - - return false; - } - -// push down from a step height above the wished position - neworg[2] += STEPSIZE; - VectorCopy (neworg, end); - end[2] -= STEPSIZE*2; - - trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent); - - if (trace.allsolid) - return false; - - if (trace.startsolid) - { - neworg[2] -= STEPSIZE; - trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent); - if (trace.allsolid || trace.startsolid) - return false; - } - if (trace.fraction == 1) - { - // if monster had the ground pulled out, go ahead and fall - if ( (int)ent->v.flags & FL_PARTIALGROUND ) - { - VectorAdd (ent->v.origin, move, ent->v.origin); - if (relink) - SV_LinkEdict (ent, true); - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; -// Con_Printf ("fall down\n"); - return true; - } - - return false; // walked off an edge - } - -// check point traces down for dangling corners - VectorCopy (trace.endpos, ent->v.origin); - - if (!SV_CheckBottom (ent)) - { - if ( (int)ent->v.flags & FL_PARTIALGROUND ) - { // entity had floor mostly pulled out from underneath it - // and is trying to correct - if (relink) - SV_LinkEdict (ent, true); - return true; - } - VectorCopy (oldorg, ent->v.origin); - return false; - } - - if ( (int)ent->v.flags & FL_PARTIALGROUND ) - { -// Con_Printf ("back on ground\n"); - ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND; - } - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - -// the move is ok - if (relink) - SV_LinkEdict (ent, true); - return true; -} - - -//============================================================================ - -/* -====================== -SV_StepDirection - -Turns to the movement direction, and walks the current distance if -facing it. - -====================== -*/ -void PF_changeyaw (void); -qboolean SV_StepDirection (edict_t *ent, float yaw, float dist) -{ - vec3_t move, oldorigin; - float delta; - - ent->v.ideal_yaw = yaw; - PF_changeyaw(); - - yaw = yaw*M_PI*2 / 360; - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - - VectorCopy (ent->v.origin, oldorigin); - if (SV_movestep (ent, move, false)) - { - delta = ent->v.angles[YAW] - ent->v.ideal_yaw; - if (delta > 45 && delta < 315) - { // not turned far enough, so don't take the step - VectorCopy (oldorigin, ent->v.origin); - } - SV_LinkEdict (ent, true); - return true; - } - SV_LinkEdict (ent, true); - - return false; -} - -/* -====================== -SV_FixCheckBottom - -====================== -*/ -void SV_FixCheckBottom (edict_t *ent) -{ -// Con_Printf ("SV_FixCheckBottom\n"); - - ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND; -} - - - -/* -================ -SV_NewChaseDir - -================ -*/ -#define DI_NODIR -1 -void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) -{ - float deltax,deltay; - float d[3]; - float tdir, olddir, turnaround; - - olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 ); - turnaround = anglemod(olddir - 180); - - deltax = enemy->v.origin[0] - actor->v.origin[0]; - deltay = enemy->v.origin[1] - actor->v.origin[1]; - if (deltax>10) - d[1]= 0; - else if (deltax<-10) - d[1]= 180; - else - d[1]= DI_NODIR; - if (deltay<-10) - d[2]= 270; - else if (deltay>10) - d[2]= 90; - else - d[2]= DI_NODIR; - -// try direct route - if (d[1] != DI_NODIR && d[2] != DI_NODIR) - { - if (d[1] == 0) - tdir = d[2] == 90 ? 45 : 315; - else - tdir = d[2] == 90 ? 135 : 215; - - if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) - return; - } - -// try other directions - if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) - { - tdir=d[1]; - d[1]=d[2]; - d[2]=tdir; - } - - if (d[1]!=DI_NODIR && d[1]!=turnaround - && SV_StepDirection(actor, d[1], dist)) - return; - - if (d[2]!=DI_NODIR && d[2]!=turnaround - && SV_StepDirection(actor, d[2], dist)) - return; - -/* there is no direct path to the player, so pick another direction */ - - if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) - return; - - if (rand()&1) /*randomly determine direction of search*/ - { - for (tdir=0 ; tdir<=315 ; tdir += 45) - if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) - return; - } - else - { - for (tdir=315 ; tdir >=0 ; tdir -= 45) - if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) - return; - } - - if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) - return; - - actor->v.ideal_yaw = olddir; // can't move - -// if a bridge was pulled out from underneath a monster, it may not have -// a valid standing position at all - - if (!SV_CheckBottom (actor)) - SV_FixCheckBottom (actor); - -} - -/* -====================== -SV_CloseEnough - -====================== -*/ -qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if (goal->v.absmin[i] > ent->v.absmax[i] + dist) - return false; - if (goal->v.absmax[i] < ent->v.absmin[i] - dist) - return false; - } - return true; -} - -/* -====================== -SV_MoveToGoal - -====================== -*/ -void SV_MoveToGoal (void) -{ - edict_t *ent, *goal; - float dist; -#ifdef QUAKE2 - edict_t *enemy; -#endif - - ent = PROG_TO_EDICT(pr_global_struct->self); - goal = PROG_TO_EDICT(ent->v.goalentity); - dist = G_FLOAT(OFS_PARM0); - - if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) - { - G_FLOAT(OFS_RETURN) = 0; - return; - } - -// if the next step hits the enemy, return immediately -#ifdef QUAKE2 - enemy = PROG_TO_EDICT(ent->v.enemy); - if (enemy != sv.edicts && SV_CloseEnough (ent, enemy, dist) ) -#else - if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) ) -#endif - return; - -// bump around... - if ( (rand()&3)==1 || - !SV_StepDirection (ent, ent->v.ideal_yaw, dist)) - { - SV_NewChaseDir (ent, goal, dist); - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_move.c -- monster movement + +#include "quakedef.h" + +#define STEPSIZE 18 + +/* +============= +SV_CheckBottom + +Returns false if any part of the bottom of the entity is off an edge that +is not a staircase. + +============= +*/ +int c_yes, c_no; + +qboolean SV_CheckBottom (edict_t *ent) +{ + vec3_t mins, maxs, start, stop; + trace_t trace; + int x, y; + float mid, bottom; + + VectorAdd (ent->v.origin, ent->v.mins, mins); + VectorAdd (ent->v.origin, ent->v.maxs, maxs); + +// if all of the points under the corners are solid world, don't bother +// with the tougher checks +// the corners must be within 16 of the midpoint + start[2] = mins[2] - 1; + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = x ? maxs[0] : mins[0]; + start[1] = y ? maxs[1] : mins[1]; + if (SV_PointContents (start) != CONTENTS_SOLID) + goto realcheck; + } + + c_yes++; + return true; // we got out easy + +realcheck: + c_no++; +// +// check it for real... +// + start[2] = mins[2]; + +// the midpoint must be within 16 of the bottom + start[0] = stop[0] = (mins[0] + maxs[0])*0.5; + start[1] = stop[1] = (mins[1] + maxs[1])*0.5; + stop[2] = start[2] - 2*STEPSIZE; + trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent); + + if (trace.fraction == 1.0) + return false; + mid = bottom = trace.endpos[2]; + +// the corners must be within 16 of the midpoint + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = stop[0] = x ? maxs[0] : mins[0]; + start[1] = stop[1] = y ? maxs[1] : mins[1]; + + trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent); + + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) + bottom = trace.endpos[2]; + if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) + return false; + } + + c_yes++; + return true; +} + + +/* +============= +SV_movestep + +Called by monster program code. +The move will be adjusted for slopes and stairs, but if the move isn't +possible, no move is done, false is returned, and +pr_global_struct->trace_normal is set to the normal of the blocking wall +============= +*/ +qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink) +{ + float dz; + vec3_t oldorg, neworg, end; + trace_t trace; + int i; + edict_t *enemy; + +// try the move + VectorCopy (ent->v.origin, oldorg); + VectorAdd (ent->v.origin, move, neworg); + +// flying monsters don't step up + if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) ) + { + // try one move with vertical motion, then one without + for (i=0 ; i<2 ; i++) + { + VectorAdd (ent->v.origin, move, neworg); + enemy = PROG_TO_EDICT(ent->v.enemy); + if (i == 0 && enemy != sv.edicts) + { + dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2]; + if (dz > 40) + neworg[2] -= 8; + if (dz < 30) + neworg[2] += 8; + } + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent); + + if (trace.fraction == 1) + { + if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY ) + return false; // swim monster left water + + VectorCopy (trace.endpos, ent->v.origin); + if (relink) + SV_LinkEdict (ent, true); + return true; + } + + if (enemy == sv.edicts) + break; + } + + return false; + } + +// push down from a step height above the wished position + neworg[2] += STEPSIZE; + VectorCopy (neworg, end); + end[2] -= STEPSIZE*2; + + trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent); + + if (trace.allsolid) + return false; + + if (trace.startsolid) + { + neworg[2] -= STEPSIZE; + trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent); + if (trace.allsolid || trace.startsolid) + return false; + } + if (trace.fraction == 1) + { + // if monster had the ground pulled out, go ahead and fall + if ( (int)ent->v.flags & FL_PARTIALGROUND ) + { + VectorAdd (ent->v.origin, move, ent->v.origin); + if (relink) + SV_LinkEdict (ent, true); + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; +// Con_Printf ("fall down\n"); + return true; + } + + return false; // walked off an edge + } + +// check point traces down for dangling corners + VectorCopy (trace.endpos, ent->v.origin); + + if (!SV_CheckBottom (ent)) + { + if ( (int)ent->v.flags & FL_PARTIALGROUND ) + { // entity had floor mostly pulled out from underneath it + // and is trying to correct + if (relink) + SV_LinkEdict (ent, true); + return true; + } + VectorCopy (oldorg, ent->v.origin); + return false; + } + + if ( (int)ent->v.flags & FL_PARTIALGROUND ) + { +// Con_Printf ("back on ground\n"); + ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND; + } + ent->v.groundentity = EDICT_TO_PROG(trace.ent); + +// the move is ok + if (relink) + SV_LinkEdict (ent, true); + return true; +} + + +//============================================================================ + +/* +====================== +SV_StepDirection + +Turns to the movement direction, and walks the current distance if +facing it. + +====================== +*/ +void PF_changeyaw (void); +qboolean SV_StepDirection (edict_t *ent, float yaw, float dist) +{ + vec3_t move, oldorigin; + float delta; + + ent->v.ideal_yaw = yaw; + PF_changeyaw(); + + yaw = yaw*M_PI*2 / 360; + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + + VectorCopy (ent->v.origin, oldorigin); + if (SV_movestep (ent, move, false)) + { + delta = ent->v.angles[YAW] - ent->v.ideal_yaw; + if (delta > 45 && delta < 315) + { // not turned far enough, so don't take the step + VectorCopy (oldorigin, ent->v.origin); + } + SV_LinkEdict (ent, true); + return true; + } + SV_LinkEdict (ent, true); + + return false; +} + +/* +====================== +SV_FixCheckBottom + +====================== +*/ +void SV_FixCheckBottom (edict_t *ent) +{ +// Con_Printf ("SV_FixCheckBottom\n"); + + ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND; +} + + + +/* +================ +SV_NewChaseDir + +================ +*/ +#define DI_NODIR -1 +void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) +{ + float deltax,deltay; + float d[3]; + float tdir, olddir, turnaround; + + olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 ); + turnaround = anglemod(olddir - 180); + + deltax = enemy->v.origin[0] - actor->v.origin[0]; + deltay = enemy->v.origin[1] - actor->v.origin[1]; + if (deltax>10) + d[1]= 0; + else if (deltax<-10) + d[1]= 180; + else + d[1]= DI_NODIR; + if (deltay<-10) + d[2]= 270; + else if (deltay>10) + d[2]= 90; + else + d[2]= DI_NODIR; + +// try direct route + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + if (d[1] == 0) + tdir = d[2] == 90 ? 45 : 315; + else + tdir = d[2] == 90 ? 135 : 215; + + if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) + return; + } + +// try other directions + if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) + { + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; + } + + if (d[1]!=DI_NODIR && d[1]!=turnaround + && SV_StepDirection(actor, d[1], dist)) + return; + + if (d[2]!=DI_NODIR && d[2]!=turnaround + && SV_StepDirection(actor, d[2], dist)) + return; + +/* there is no direct path to the player, so pick another direction */ + + if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) + return; + + if (rand()&1) /*randomly determine direction of search*/ + { + for (tdir=0 ; tdir<=315 ; tdir += 45) + if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) + return; + } + else + { + for (tdir=315 ; tdir >=0 ; tdir -= 45) + if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) + return; + } + + if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) + return; + + actor->v.ideal_yaw = olddir; // can't move + +// if a bridge was pulled out from underneath a monster, it may not have +// a valid standing position at all + + if (!SV_CheckBottom (actor)) + SV_FixCheckBottom (actor); + +} + +/* +====================== +SV_CloseEnough + +====================== +*/ +qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) +{ + int i; + + for (i=0 ; i<3 ; i++) + { + if (goal->v.absmin[i] > ent->v.absmax[i] + dist) + return false; + if (goal->v.absmax[i] < ent->v.absmin[i] - dist) + return false; + } + return true; +} + +/* +====================== +SV_MoveToGoal + +====================== +*/ +void SV_MoveToGoal (void) +{ + edict_t *ent, *goal; + float dist; +#ifdef QUAKE2 + edict_t *enemy; +#endif + + ent = PROG_TO_EDICT(pr_global_struct->self); + goal = PROG_TO_EDICT(ent->v.goalentity); + dist = G_FLOAT(OFS_PARM0); + + if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) + { + G_FLOAT(OFS_RETURN) = 0; + return; + } + +// if the next step hits the enemy, return immediately +#ifdef QUAKE2 + enemy = PROG_TO_EDICT(ent->v.enemy); + if (enemy != sv.edicts && SV_CloseEnough (ent, enemy, dist) ) +#else + if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) ) +#endif + return; + +// bump around... + if ( (rand()&3)==1 || + !SV_StepDirection (ent, ent->v.ideal_yaw, dist)) + { + SV_NewChaseDir (ent, goal, dist); + } +} + diff --git a/WinQuake/sv_phys.c b/WinQuake/sv_phys.c index e13c0e4..1e3cc73 100644 --- a/WinQuake/sv_phys.c +++ b/WinQuake/sv_phys.c @@ -1,1617 +1,1617 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_phys.c - -#include "quakedef.h" - -/* - - -pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move. - -onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects - -doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH -bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS -corpses are SOLID_NOT and MOVETYPE_TOSS -crates are SOLID_BBOX and MOVETYPE_TOSS -walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP -flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY - -solid_edge items only clip against bsp models. - -*/ - -cvar_t sv_friction = {"sv_friction","4",false,true}; -cvar_t sv_stopspeed = {"sv_stopspeed","100"}; -cvar_t sv_gravity = {"sv_gravity","800",false,true}; -cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"}; -cvar_t sv_nostep = {"sv_nostep","0"}; - -#ifdef QUAKE2 -static vec3_t vec_origin = {0.0, 0.0, 0.0}; -#endif - -#define MOVE_EPSILON 0.01 - -void SV_Physics_Toss (edict_t *ent); - -/* -================ -SV_CheckAllEnts -================ -*/ -void SV_CheckAllEnts (void) -{ - int e; - edict_t *check; - -// see if any solid entities are inside the final position - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE -#ifdef QUAKE2 - || check->v.movetype == MOVETYPE_FOLLOW -#endif - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - if (SV_TestEntityPosition (check)) - Con_Printf ("entity in invalid position\n"); - } -} - -/* -================ -SV_CheckVelocity -================ -*/ -void SV_CheckVelocity (edict_t *ent) -{ - int i; - -// -// bound velocity -// - for (i=0 ; i<3 ; i++) - { - if (IS_NAN(ent->v.velocity[i])) - { - Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname); - ent->v.velocity[i] = 0; - } - if (IS_NAN(ent->v.origin[i])) - { - Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname); - ent->v.origin[i] = 0; - } - if (ent->v.velocity[i] > sv_maxvelocity.value) - ent->v.velocity[i] = sv_maxvelocity.value; - else if (ent->v.velocity[i] < -sv_maxvelocity.value) - ent->v.velocity[i] = -sv_maxvelocity.value; - } -} - -/* -============= -SV_RunThink - -Runs thinking code if time. There is some play in the exact time the think -function will be called, because it is called before any movement is done -in a frame. Not used for pushmove objects, because they must be exact. -Returns false if the entity removed itself. -============= -*/ -qboolean SV_RunThink (edict_t *ent) -{ - float thinktime; - - thinktime = ent->v.nextthink; - if (thinktime <= 0 || thinktime > sv.time + host_frametime) - return true; - - if (thinktime < sv.time) - thinktime = sv.time; // don't let things stay in the past. - // it is possible to start that way - // by a trigger with a local time. - ent->v.nextthink = 0; - pr_global_struct->time = thinktime; - pr_global_struct->self = EDICT_TO_PROG(ent); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - PR_ExecuteProgram (ent->v.think); - return !ent->free; -} - -/* -================== -SV_Impact - -Two entities have touched, so run their touch functions -================== -*/ -void SV_Impact (edict_t *e1, edict_t *e2) -{ - int old_self, old_other; - - old_self = pr_global_struct->self; - old_other = pr_global_struct->other; - - pr_global_struct->time = sv.time; - if (e1->v.touch && e1->v.solid != SOLID_NOT) - { - pr_global_struct->self = EDICT_TO_PROG(e1); - pr_global_struct->other = EDICT_TO_PROG(e2); - PR_ExecuteProgram (e1->v.touch); - } - - if (e2->v.touch && e2->v.solid != SOLID_NOT) - { - pr_global_struct->self = EDICT_TO_PROG(e2); - pr_global_struct->other = EDICT_TO_PROG(e1); - PR_ExecuteProgram (e2->v.touch); - } - - pr_global_struct->self = old_self; - pr_global_struct->other = old_other; -} - - -/* -================== -ClipVelocity - -Slide off of the impacting object -returns the blocked flags (1 = floor, 2 = step / wall) -================== -*/ -#define STOP_EPSILON 0.1 - -int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) -{ - float backoff; - float change; - int i, blocked; - - blocked = 0; - if (normal[2] > 0) - blocked |= 1; // floor - if (!normal[2]) - blocked |= 2; // step - - backoff = DotProduct (in, normal) * overbounce; - - for (i=0 ; i<3 ; i++) - { - change = normal[i]*backoff; - out[i] = in[i] - change; - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) - out[i] = 0; - } - - return blocked; -} - - -/* -============ -SV_FlyMove - -The basic solid body movement clip that slides along multiple planes -Returns the clipflags if the velocity was modified (hit something solid) -1 = floor -2 = wall / step -4 = dead stop -If steptrace is not NULL, the trace of any vertical wall hit will be stored -============ -*/ -#define MAX_CLIP_PLANES 5 -int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) -{ - int bumpcount, numbumps; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[MAX_CLIP_PLANES]; - vec3_t primal_velocity, original_velocity, new_velocity; - int i, j; - trace_t trace; - vec3_t end; - float time_left; - int blocked; - - numbumps = 4; - - blocked = 0; - VectorCopy (ent->v.velocity, original_velocity); - VectorCopy (ent->v.velocity, primal_velocity); - numplanes = 0; - - time_left = time; - - for (bumpcount=0 ; bumpcountv.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) - break; - - for (i=0 ; i<3 ; i++) - end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); - - if (trace.allsolid) - { // entity is trapped in another solid - VectorCopy (vec3_origin, ent->v.velocity); - return 3; - } - - if (trace.fraction > 0) - { // actually covered some distance - VectorCopy (trace.endpos, ent->v.origin); - VectorCopy (ent->v.velocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; // moved the entire distance - - if (!trace.ent) - Sys_Error ("SV_FlyMove: !trace.ent"); - - if (trace.plane.normal[2] > 0.7) - { - blocked |= 1; // floor - if (trace.ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - } - } - if (!trace.plane.normal[2]) - { - blocked |= 2; // step - if (steptrace) - *steptrace = trace; // save for player extrafriction - } - -// -// run the impact function -// - SV_Impact (ent, trace.ent); - if (ent->free) - break; // removed by the impact function - - - time_left -= time_left * trace.fraction; - - // cliped to another plane - if (numplanes >= MAX_CLIP_PLANES) - { // this shouldn't really happen - VectorCopy (vec3_origin, ent->v.velocity); - return 3; - } - - VectorCopy (trace.plane.normal, planes[numplanes]); - numplanes++; - -// -// modify original_velocity so it parallels all of the clip planes -// - for (i=0 ; iv.velocity); - } - else - { // go along the crease - if (numplanes != 2) - { -// Con_Printf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy (vec3_origin, ent->v.velocity); - return 7; - } - CrossProduct (planes[0], planes[1], dir); - d = DotProduct (dir, ent->v.velocity); - VectorScale (dir, d, ent->v.velocity); - } - -// -// if original velocity is against the original velocity, stop dead -// to avoid tiny occilations in sloping corners -// - if (DotProduct (ent->v.velocity, primal_velocity) <= 0) - { - VectorCopy (vec3_origin, ent->v.velocity); - return blocked; - } - } - - return blocked; -} - - -/* -============ -SV_AddGravity - -============ -*/ -void SV_AddGravity (edict_t *ent) -{ - float ent_gravity; - -#ifdef QUAKE2 - if (ent->v.gravity) - ent_gravity = ent->v.gravity; - else - ent_gravity = 1.0; -#else - eval_t *val; - - val = GetEdictFieldValue(ent, "gravity"); - if (val && val->_float) - ent_gravity = val->_float; - else - ent_gravity = 1.0; -#endif - ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime; -} - - -/* -=============================================================================== - -PUSHMOVE - -=============================================================================== -*/ - -/* -============ -SV_PushEntity - -Does not change the entities velocity at all -============ -*/ -trace_t SV_PushEntity (edict_t *ent, vec3_t push) -{ - trace_t trace; - vec3_t end; - - VectorAdd (ent->v.origin, push, end); - - if (ent->v.movetype == MOVETYPE_FLYMISSILE) - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent); - else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT) - // only clip against bmodels - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent); - else - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); - - VectorCopy (trace.endpos, ent->v.origin); - SV_LinkEdict (ent, true); - - if (trace.ent) - SV_Impact (ent, trace.ent); - - return trace; -} - - -/* -============ -SV_PushMove - -============ -*/ -void SV_PushMove (edict_t *pusher, float movetime) -{ - int i, e; - edict_t *check, *block; - vec3_t mins, maxs, move; - vec3_t entorig, pushorig; - int num_moved; - edict_t *moved_edict[MAX_EDICTS]; - vec3_t moved_from[MAX_EDICTS]; - - if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) - { - pusher->v.ltime += movetime; - return; - } - - for (i=0 ; i<3 ; i++) - { - move[i] = pusher->v.velocity[i] * movetime; - mins[i] = pusher->v.absmin[i] + move[i]; - maxs[i] = pusher->v.absmax[i] + move[i]; - } - - VectorCopy (pusher->v.origin, pushorig); - -// move the pusher to it's final position - - VectorAdd (pusher->v.origin, move, pusher->v.origin); - pusher->v.ltime += movetime; - SV_LinkEdict (pusher, false); - - -// see if any solid entities are inside the final position - num_moved = 0; - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE -#ifdef QUAKE2 - || check->v.movetype == MOVETYPE_FOLLOW -#endif - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - // if the entity is standing on the pusher, it will definately be moved - if ( ! ( ((int)check->v.flags & FL_ONGROUND) - && PROG_TO_EDICT(check->v.groundentity) == pusher) ) - { - if ( check->v.absmin[0] >= maxs[0] - || check->v.absmin[1] >= maxs[1] - || check->v.absmin[2] >= maxs[2] - || check->v.absmax[0] <= mins[0] - || check->v.absmax[1] <= mins[1] - || check->v.absmax[2] <= mins[2] ) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - // remove the onground flag for non-players - if (check->v.movetype != MOVETYPE_WALK) - check->v.flags = (int)check->v.flags & ~FL_ONGROUND; - - VectorCopy (check->v.origin, entorig); - VectorCopy (check->v.origin, moved_from[num_moved]); - moved_edict[num_moved] = check; - num_moved++; - - // try moving the contacted entity - pusher->v.solid = SOLID_NOT; - SV_PushEntity (check, move); - pusher->v.solid = SOLID_BSP; - - // if it is still inside the pusher, block - block = SV_TestEntityPosition (check); - if (block) - { // fail the move - if (check->v.mins[0] == check->v.maxs[0]) - continue; - if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) - { // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy (check->v.mins, check->v.maxs); - continue; - } - - VectorCopy (entorig, check->v.origin); - SV_LinkEdict (check, true); - - VectorCopy (pushorig, pusher->v.origin); - SV_LinkEdict (pusher, false); - pusher->v.ltime -= movetime; - - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - if (pusher->v.blocked) - { - pr_global_struct->self = EDICT_TO_PROG(pusher); - pr_global_struct->other = EDICT_TO_PROG(check); - PR_ExecuteProgram (pusher->v.blocked); - } - - // move back any entities we already moved - for (i=0 ; iv.origin); - SV_LinkEdict (moved_edict[i], false); - } - return; - } - } - - -} - -#ifdef QUAKE2 -/* -============ -SV_PushRotate - -============ -*/ -void SV_PushRotate (edict_t *pusher, float movetime) -{ - int i, e; - edict_t *check, *block; - vec3_t move, a, amove; - vec3_t entorig, pushorig; - int num_moved; - edict_t *moved_edict[MAX_EDICTS]; - vec3_t moved_from[MAX_EDICTS]; - vec3_t org, org2; - vec3_t forward, right, up; - - if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2]) - { - pusher->v.ltime += movetime; - return; - } - - for (i=0 ; i<3 ; i++) - amove[i] = pusher->v.avelocity[i] * movetime; - - VectorSubtract (vec3_origin, amove, a); - AngleVectors (a, forward, right, up); - - VectorCopy (pusher->v.angles, pushorig); - -// move the pusher to it's final position - - VectorAdd (pusher->v.angles, amove, pusher->v.angles); - pusher->v.ltime += movetime; - SV_LinkEdict (pusher, false); - - -// see if any solid entities are inside the final position - num_moved = 0; - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_FOLLOW - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - // if the entity is standing on the pusher, it will definately be moved - if ( ! ( ((int)check->v.flags & FL_ONGROUND) - && PROG_TO_EDICT(check->v.groundentity) == pusher) ) - { - if ( check->v.absmin[0] >= pusher->v.absmax[0] - || check->v.absmin[1] >= pusher->v.absmax[1] - || check->v.absmin[2] >= pusher->v.absmax[2] - || check->v.absmax[0] <= pusher->v.absmin[0] - || check->v.absmax[1] <= pusher->v.absmin[1] - || check->v.absmax[2] <= pusher->v.absmin[2] ) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - // remove the onground flag for non-players - if (check->v.movetype != MOVETYPE_WALK) - check->v.flags = (int)check->v.flags & ~FL_ONGROUND; - - VectorCopy (check->v.origin, entorig); - VectorCopy (check->v.origin, moved_from[num_moved]); - moved_edict[num_moved] = check; - num_moved++; - - // calculate destination position - VectorSubtract (check->v.origin, pusher->v.origin, org); - org2[0] = DotProduct (org, forward); - org2[1] = -DotProduct (org, right); - org2[2] = DotProduct (org, up); - VectorSubtract (org2, org, move); - - // try moving the contacted entity - pusher->v.solid = SOLID_NOT; - SV_PushEntity (check, move); - pusher->v.solid = SOLID_BSP; - - // if it is still inside the pusher, block - block = SV_TestEntityPosition (check); - if (block) - { // fail the move - if (check->v.mins[0] == check->v.maxs[0]) - continue; - if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) - { // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy (check->v.mins, check->v.maxs); - continue; - } - - VectorCopy (entorig, check->v.origin); - SV_LinkEdict (check, true); - - VectorCopy (pushorig, pusher->v.angles); - SV_LinkEdict (pusher, false); - pusher->v.ltime -= movetime; - - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - if (pusher->v.blocked) - { - pr_global_struct->self = EDICT_TO_PROG(pusher); - pr_global_struct->other = EDICT_TO_PROG(check); - PR_ExecuteProgram (pusher->v.blocked); - } - - // move back any entities we already moved - for (i=0 ; iv.origin); - VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); - SV_LinkEdict (moved_edict[i], false); - } - return; - } - else - { - VectorAdd (check->v.angles, amove, check->v.angles); - } - } - - -} -#endif - -/* -================ -SV_Physics_Pusher - -================ -*/ -void SV_Physics_Pusher (edict_t *ent) -{ - float thinktime; - float oldltime; - float movetime; - - oldltime = ent->v.ltime; - - thinktime = ent->v.nextthink; - if (thinktime < ent->v.ltime + host_frametime) - { - movetime = thinktime - ent->v.ltime; - if (movetime < 0) - movetime = 0; - } - else - movetime = host_frametime; - - if (movetime) - { -#ifdef QUAKE2 - if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2]) - SV_PushRotate (ent, movetime); - else -#endif - SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked - } - - if (thinktime > oldltime && thinktime <= ent->v.ltime) - { - ent->v.nextthink = 0; - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - PR_ExecuteProgram (ent->v.think); - if (ent->free) - return; - } - -} - - -/* -=============================================================================== - -CLIENT MOVEMENT - -=============================================================================== -*/ - -/* -============= -SV_CheckStuck - -This is a big hack to try and fix the rare case of getting stuck in the world -clipping hull. -============= -*/ -void SV_CheckStuck (edict_t *ent) -{ - int i, j; - int z; - vec3_t org; - - if (!SV_TestEntityPosition(ent)) - { - VectorCopy (ent->v.origin, ent->v.oldorigin); - return; - } - - VectorCopy (ent->v.origin, org); - VectorCopy (ent->v.oldorigin, ent->v.origin); - if (!SV_TestEntityPosition(ent)) - { - Con_DPrintf ("Unstuck.\n"); - SV_LinkEdict (ent, true); - return; - } - - for (z=0 ; z< 18 ; z++) - for (i=-1 ; i <= 1 ; i++) - for (j=-1 ; j <= 1 ; j++) - { - ent->v.origin[0] = org[0] + i; - ent->v.origin[1] = org[1] + j; - ent->v.origin[2] = org[2] + z; - if (!SV_TestEntityPosition(ent)) - { - Con_DPrintf ("Unstuck.\n"); - SV_LinkEdict (ent, true); - return; - } - } - - VectorCopy (org, ent->v.origin); - Con_DPrintf ("player is stuck.\n"); -} - - -/* -============= -SV_CheckWater -============= -*/ -qboolean SV_CheckWater (edict_t *ent) -{ - vec3_t point; - int cont; -#ifdef QUAKE2 - int truecont; -#endif - - point[0] = ent->v.origin[0]; - point[1] = ent->v.origin[1]; - point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; - - ent->v.waterlevel = 0; - ent->v.watertype = CONTENTS_EMPTY; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - { -#ifdef QUAKE2 - truecont = SV_TruePointContents (point); -#endif - ent->v.watertype = cont; - ent->v.waterlevel = 1; - point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - { - ent->v.waterlevel = 2; - point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - ent->v.waterlevel = 3; - } -#ifdef QUAKE2 - if (truecont <= CONTENTS_CURRENT_0 && truecont >= CONTENTS_CURRENT_DOWN) - { - static vec3_t current_table[] = - { - {1, 0, 0}, - {0, 1, 0}, - {-1, 0, 0}, - {0, -1, 0}, - {0, 0, 1}, - {0, 0, -1} - }; - - VectorMA (ent->v.basevelocity, 150.0*ent->v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->v.basevelocity); - } -#endif - } - - return ent->v.waterlevel > 1; -} - -/* -============ -SV_WallFriction - -============ -*/ -void SV_WallFriction (edict_t *ent, trace_t *trace) -{ - vec3_t forward, right, up; - float d, i; - vec3_t into, side; - - AngleVectors (ent->v.v_angle, forward, right, up); - d = DotProduct (trace->plane.normal, forward); - - d += 0.5; - if (d >= 0) - return; - -// cut the tangential velocity - i = DotProduct (trace->plane.normal, ent->v.velocity); - VectorScale (trace->plane.normal, i, into); - VectorSubtract (ent->v.velocity, into, side); - - ent->v.velocity[0] = side[0] * (1 + d); - ent->v.velocity[1] = side[1] * (1 + d); -} - -/* -===================== -SV_TryUnstick - -Player has come to a dead stop, possibly due to the problem with limited -float precision at some angle joins in the BSP hull. - -Try fixing by pushing one pixel in each direction. - -This is a hack, but in the interest of good gameplay... -====================== -*/ -int SV_TryUnstick (edict_t *ent, vec3_t oldvel) -{ - int i; - vec3_t oldorg; - vec3_t dir; - int clip; - trace_t steptrace; - - VectorCopy (ent->v.origin, oldorg); - VectorCopy (vec3_origin, dir); - - for (i=0 ; i<8 ; i++) - { -// try pushing a little in an axial direction - switch (i) - { - case 0: dir[0] = 2; dir[1] = 0; break; - case 1: dir[0] = 0; dir[1] = 2; break; - case 2: dir[0] = -2; dir[1] = 0; break; - case 3: dir[0] = 0; dir[1] = -2; break; - case 4: dir[0] = 2; dir[1] = 2; break; - case 5: dir[0] = -2; dir[1] = 2; break; - case 6: dir[0] = 2; dir[1] = -2; break; - case 7: dir[0] = -2; dir[1] = -2; break; - } - - SV_PushEntity (ent, dir); - -// retry the original move - ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, 0.1, &steptrace); - - if ( fabs(oldorg[1] - ent->v.origin[1]) > 4 - || fabs(oldorg[0] - ent->v.origin[0]) > 4 ) - { -//Con_DPrintf ("unstuck!\n"); - return clip; - } - -// go back to the original pos and try again - VectorCopy (oldorg, ent->v.origin); - } - - VectorCopy (vec3_origin, ent->v.velocity); - return 7; // still not moving -} - -/* -===================== -SV_WalkMove - -Only used by players -====================== -*/ -#define STEPSIZE 18 -void SV_WalkMove (edict_t *ent) -{ - vec3_t upmove, downmove; - vec3_t oldorg, oldvel; - vec3_t nosteporg, nostepvel; - int clip; - int oldonground; - trace_t steptrace, downtrace; - -// -// do a regular slide move unless it looks like you ran into a step -// - oldonground = (int)ent->v.flags & FL_ONGROUND; - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - - VectorCopy (ent->v.origin, oldorg); - VectorCopy (ent->v.velocity, oldvel); - - clip = SV_FlyMove (ent, host_frametime, &steptrace); - - if ( !(clip & 2) ) - return; // move didn't block on a step - - if (!oldonground && ent->v.waterlevel == 0) - return; // don't stair up while jumping - - if (ent->v.movetype != MOVETYPE_WALK) - return; // gibbed by a trigger - - if (sv_nostep.value) - return; - - if ( (int)sv_player->v.flags & FL_WATERJUMP ) - return; - - VectorCopy (ent->v.origin, nosteporg); - VectorCopy (ent->v.velocity, nostepvel); - -// -// try moving up and forward to go up a step -// - VectorCopy (oldorg, ent->v.origin); // back to start pos - - VectorCopy (vec3_origin, upmove); - VectorCopy (vec3_origin, downmove); - upmove[2] = STEPSIZE; - downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; - -// move up - SV_PushEntity (ent, upmove); // FIXME: don't link? - -// move forward - ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, host_frametime, &steptrace); - -// check for stuckness, possibly due to the limited precision of floats -// in the clipping hulls - if (clip) - { - if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 - && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 ) - { // stepping up didn't make any progress - clip = SV_TryUnstick (ent, oldvel); - } - } - -// extra friction based on view angle - if ( clip & 2 ) - SV_WallFriction (ent, &steptrace); - -// move down - downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link? - - if (downtrace.plane.normal[2] > 0.7) - { - if (ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); - } - } - else - { -// if the push down didn't end up on good ground, use the move without -// the step up. This happens near wall / slope combinations, and can -// cause the player to hop up higher on a slope too steep to climb - VectorCopy (nosteporg, ent->v.origin); - VectorCopy (nostepvel, ent->v.velocity); - } -} - - -/* -================ -SV_Physics_Client - -Player character actions -================ -*/ -void SV_Physics_Client (edict_t *ent, int num) -{ - if ( ! svs.clients[num-1].active ) - return; // unconnected slot - -// -// call standard client pre-think -// - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPreThink); - -// -// do a move -// - SV_CheckVelocity (ent); - -// -// decide which move function to call -// - switch ((int)ent->v.movetype) - { - case MOVETYPE_NONE: - if (!SV_RunThink (ent)) - return; - break; - - case MOVETYPE_WALK: - if (!SV_RunThink (ent)) - return; - if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); -#ifdef QUAKE2 - VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); -#endif - SV_WalkMove (ent); - -#ifdef QUAKE2 - VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); -#endif - break; - - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - SV_Physics_Toss (ent); - break; - - case MOVETYPE_FLY: - if (!SV_RunThink (ent)) - return; - SV_FlyMove (ent, host_frametime, NULL); - break; - - case MOVETYPE_NOCLIP: - if (!SV_RunThink (ent)) - return; - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); - break; - - default: - Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); - } - -// -// call standard player post-think -// - SV_LinkEdict (ent, true); - - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPostThink); -} - -//============================================================================ - -/* -============= -SV_Physics_None - -Non moving objects can only think -============= -*/ -void SV_Physics_None (edict_t *ent) -{ -// regular thinking - SV_RunThink (ent); -} - -#ifdef QUAKE2 -/* -============= -SV_Physics_Follow - -Entities that are "stuck" to another entity -============= -*/ -void SV_Physics_Follow (edict_t *ent) -{ -// regular thinking - SV_RunThink (ent); - VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin); - SV_LinkEdict (ent, true); -} -#endif - -/* -============= -SV_Physics_Noclip - -A moving object that doesn't obey physics -============= -*/ -void SV_Physics_Noclip (edict_t *ent) -{ -// regular thinking - if (!SV_RunThink (ent)) - return; - - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); - - SV_LinkEdict (ent, false); -} - -/* -============================================================================== - -TOSS / BOUNCE - -============================================================================== -*/ - -/* -============= -SV_CheckWaterTransition - -============= -*/ -void SV_CheckWaterTransition (edict_t *ent) -{ - int cont; -#ifdef QUAKE2 - vec3_t point; - - point[0] = ent->v.origin[0]; - point[1] = ent->v.origin[1]; - point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; - cont = SV_PointContents (point); -#else - cont = SV_PointContents (ent->v.origin); -#endif - if (!ent->v.watertype) - { // just spawned here - ent->v.watertype = cont; - ent->v.waterlevel = 1; - return; - } - - if (cont <= CONTENTS_WATER) - { - if (ent->v.watertype == CONTENTS_EMPTY) - { // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } - ent->v.watertype = cont; - ent->v.waterlevel = 1; - } - else - { - if (ent->v.watertype != CONTENTS_EMPTY) - { // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } - ent->v.watertype = CONTENTS_EMPTY; - ent->v.waterlevel = cont; - } -} - -/* -============= -SV_Physics_Toss - -Toss, bounce, and fly movement. When onground, do nothing. -============= -*/ -void SV_Physics_Toss (edict_t *ent) -{ - trace_t trace; - vec3_t move; - float backoff; -#ifdef QUAKE2 - edict_t *groundentity; - - groundentity = PROG_TO_EDICT(ent->v.groundentity); - if ((int)groundentity->v.flags & FL_CONVEYOR) - VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity); - else - VectorCopy(vec_origin, ent->v.basevelocity); - SV_CheckWater (ent); -#endif - // regular thinking - if (!SV_RunThink (ent)) - return; - -#ifdef QUAKE2 - if (ent->v.velocity[2] > 0) - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - - if ( ((int)ent->v.flags & FL_ONGROUND) ) -//@@ - if (VectorCompare(ent->v.basevelocity, vec_origin)) - return; - - SV_CheckVelocity (ent); - -// add gravity - if (! ((int)ent->v.flags & FL_ONGROUND) - && ent->v.movetype != MOVETYPE_FLY - && ent->v.movetype != MOVETYPE_BOUNCEMISSILE - && ent->v.movetype != MOVETYPE_FLYMISSILE) - SV_AddGravity (ent); - -#else -// if onground, return without moving - if ( ((int)ent->v.flags & FL_ONGROUND) ) - return; - - SV_CheckVelocity (ent); - -// add gravity - if (ent->v.movetype != MOVETYPE_FLY - && ent->v.movetype != MOVETYPE_FLYMISSILE) - SV_AddGravity (ent); -#endif - -// move angles - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); - -// move origin -#ifdef QUAKE2 - VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); -#endif - VectorScale (ent->v.velocity, host_frametime, move); - trace = SV_PushEntity (ent, move); -#ifdef QUAKE2 - VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); -#endif - if (trace.fraction == 1) - return; - if (ent->free) - return; - - if (ent->v.movetype == MOVETYPE_BOUNCE) - backoff = 1.5; -#ifdef QUAKE2 - else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE) - backoff = 2.0; -#endif - else - backoff = 1; - - ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); - -// stop if on ground - if (trace.plane.normal[2] > 0.7) - { -#ifdef QUAKE2 - if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE)) -#else - if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) -#endif - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, ent->v.velocity); - VectorCopy (vec3_origin, ent->v.avelocity); - } - } - -// check for in water - SV_CheckWaterTransition (ent); -} - -/* -=============================================================================== - -STEPPING MOVEMENT - -=============================================================================== -*/ - -/* -============= -SV_Physics_Step - -Monsters freefall when they don't have a ground entity, otherwise -all movement is done with discrete steps. - -This is also used for objects that have become still on the ground, but -will fall if the floor is pulled out from under them. -============= -*/ -#ifdef QUAKE2 -void SV_Physics_Step (edict_t *ent) -{ - qboolean wasonground; - qboolean inwater; - qboolean hitsound = false; - float *vel; - float speed, newspeed, control; - float friction; - edict_t *groundentity; - - groundentity = PROG_TO_EDICT(ent->v.groundentity); - if ((int)groundentity->v.flags & FL_CONVEYOR) - VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity); - else - VectorCopy(vec_origin, ent->v.basevelocity); -//@@ - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PF_WaterMove(); - - SV_CheckVelocity (ent); - - wasonground = (int)ent->v.flags & FL_ONGROUND; -// ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - - // add gravity except: - // flying monsters - // swimming monsters who are in the water - inwater = SV_CheckWater(ent); - if (! wasonground) - if (!((int)ent->v.flags & FL_FLY)) - if (!(((int)ent->v.flags & FL_SWIM) && (ent->v.waterlevel > 0))) - { - if (ent->v.velocity[2] < sv_gravity.value*-0.1) - hitsound = true; - if (!inwater) - SV_AddGravity (ent); - } - - if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin)) - { - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - // apply friction - // let dead monsters who aren't completely onground slide - if (wasonground) - if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent))) - { - vel = ent->v.velocity; - speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); - if (speed) - { - friction = sv_friction.value; - - control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; - newspeed = speed - host_frametime*control*friction; - - if (newspeed < 0) - newspeed = 0; - newspeed /= speed; - - vel[0] = vel[0] * newspeed; - vel[1] = vel[1] * newspeed; - } - } - - VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); - SV_FlyMove (ent, host_frametime, NULL); - VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); - - // determine if it's on solid ground at all - { - vec3_t mins, maxs, point; - int x, y; - - VectorAdd (ent->v.origin, ent->v.mins, mins); - VectorAdd (ent->v.origin, ent->v.maxs, maxs); - - point[2] = mins[2] - 1; - for (x=0 ; x<=1 ; x++) - for (y=0 ; y<=1 ; y++) - { - point[0] = x ? maxs[0] : mins[0]; - point[1] = y ? maxs[1] : mins[1]; - if (SV_PointContents (point) == CONTENTS_SOLID) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - break; - } - } - - } - - SV_LinkEdict (ent, true); - - if ((int)ent->v.flags & FL_ONGROUND) - if (!wasonground) - if (hitsound) - SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); - } - -// regular thinking - SV_RunThink (ent); - SV_CheckWaterTransition (ent); -} -#else -void SV_Physics_Step (edict_t *ent) -{ - qboolean hitsound; - -// freefall if not onground - if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) - { - if (ent->v.velocity[2] < sv_gravity.value*-0.1) - hitsound = true; - else - hitsound = false; - - SV_AddGravity (ent); - SV_CheckVelocity (ent); - SV_FlyMove (ent, host_frametime, NULL); - SV_LinkEdict (ent, true); - - if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground - { - if (hitsound) - SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); - } - } - -// regular thinking - SV_RunThink (ent); - - SV_CheckWaterTransition (ent); -} -#endif - -//============================================================================ - -/* -================ -SV_Physics - -================ -*/ -void SV_Physics (void) -{ - int i; - edict_t *ent; - -// let the progs know that a new frame has started - pr_global_struct->self = EDICT_TO_PROG(sv.edicts); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - pr_global_struct->time = sv.time; - PR_ExecuteProgram (pr_global_struct->StartFrame); - -//SV_CheckAllEnts (); - -// -// treat each object in turn -// - ent = sv.edicts; - for (i=0 ; ifree) - continue; - - if (pr_global_struct->force_retouch) - { - SV_LinkEdict (ent, true); // force retouch even for stationary - } - - if (i > 0 && i <= svs.maxclients) - SV_Physics_Client (ent, i); - else if (ent->v.movetype == MOVETYPE_PUSH) - SV_Physics_Pusher (ent); - else if (ent->v.movetype == MOVETYPE_NONE) - SV_Physics_None (ent); -#ifdef QUAKE2 - else if (ent->v.movetype == MOVETYPE_FOLLOW) - SV_Physics_Follow (ent); -#endif - else if (ent->v.movetype == MOVETYPE_NOCLIP) - SV_Physics_Noclip (ent); - else if (ent->v.movetype == MOVETYPE_STEP) - SV_Physics_Step (ent); - else if (ent->v.movetype == MOVETYPE_TOSS - || ent->v.movetype == MOVETYPE_BOUNCE -#ifdef QUAKE2 - || ent->v.movetype == MOVETYPE_BOUNCEMISSILE -#endif - || ent->v.movetype == MOVETYPE_FLY - || ent->v.movetype == MOVETYPE_FLYMISSILE) - SV_Physics_Toss (ent); - else - Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); - } - - if (pr_global_struct->force_retouch) - pr_global_struct->force_retouch--; - - sv.time += host_frametime; -} - - -#ifdef QUAKE2 -trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) -{ - edict_t tempent, *tent; - trace_t trace; - vec3_t move; - vec3_t end; - double save_frametime; -// extern particle_t *active_particles, *free_particles; -// particle_t *p; - - - save_frametime = host_frametime; - host_frametime = 0.05; - - memcpy(&tempent, ent, sizeof(edict_t)); - tent = &tempent; - - while (1) - { - SV_CheckVelocity (tent); - SV_AddGravity (tent); - VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles); - VectorScale (tent->v.velocity, host_frametime, move); - VectorAdd (tent->v.origin, move, end); - trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent); - VectorCopy (trace.endpos, tent->v.origin); - -// p = free_particles; -// if (p) -// { -// free_particles = p->next; -// p->next = active_particles; -// active_particles = p; -// -// p->die = 256; -// p->color = 15; -// p->type = pt_static; -// VectorCopy (vec3_origin, p->vel); -// VectorCopy (tent->v.origin, p->org); -// } - - if (trace.ent) - if (trace.ent != ignore) - break; - } -// p->color = 224; - host_frametime = save_frametime; - return trace; -} -#endif +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_phys.c + +#include "quakedef.h" + +/* + + +pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move. + +onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects + +doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH +bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS +corpses are SOLID_NOT and MOVETYPE_TOSS +crates are SOLID_BBOX and MOVETYPE_TOSS +walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP +flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY + +solid_edge items only clip against bsp models. + +*/ + +cvar_t sv_friction = {"sv_friction","4",false,true}; +cvar_t sv_stopspeed = {"sv_stopspeed","100"}; +cvar_t sv_gravity = {"sv_gravity","800",false,true}; +cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"}; +cvar_t sv_nostep = {"sv_nostep","0"}; + +#ifdef QUAKE2 +static vec3_t vec_origin = {0.0, 0.0, 0.0}; +#endif + +#define MOVE_EPSILON 0.01 + +void SV_Physics_Toss (edict_t *ent); + +/* +================ +SV_CheckAllEnts +================ +*/ +void SV_CheckAllEnts (void) +{ + int e; + edict_t *check; + +// see if any solid entities are inside the final position + check = NEXT_EDICT(sv.edicts); + for (e=1 ; efree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE +#ifdef QUAKE2 + || check->v.movetype == MOVETYPE_FOLLOW +#endif + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + if (SV_TestEntityPosition (check)) + Con_Printf ("entity in invalid position\n"); + } +} + +/* +================ +SV_CheckVelocity +================ +*/ +void SV_CheckVelocity (edict_t *ent) +{ + int i; + +// +// bound velocity +// + for (i=0 ; i<3 ; i++) + { + if (IS_NAN(ent->v.velocity[i])) + { + Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname); + ent->v.velocity[i] = 0; + } + if (IS_NAN(ent->v.origin[i])) + { + Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname); + ent->v.origin[i] = 0; + } + if (ent->v.velocity[i] > sv_maxvelocity.value) + ent->v.velocity[i] = sv_maxvelocity.value; + else if (ent->v.velocity[i] < -sv_maxvelocity.value) + ent->v.velocity[i] = -sv_maxvelocity.value; + } +} + +/* +============= +SV_RunThink + +Runs thinking code if time. There is some play in the exact time the think +function will be called, because it is called before any movement is done +in a frame. Not used for pushmove objects, because they must be exact. +Returns false if the entity removed itself. +============= +*/ +qboolean SV_RunThink (edict_t *ent) +{ + float thinktime; + + thinktime = ent->v.nextthink; + if (thinktime <= 0 || thinktime > sv.time + host_frametime) + return true; + + if (thinktime < sv.time) + thinktime = sv.time; // don't let things stay in the past. + // it is possible to start that way + // by a trigger with a local time. + ent->v.nextthink = 0; + pr_global_struct->time = thinktime; + pr_global_struct->self = EDICT_TO_PROG(ent); + pr_global_struct->other = EDICT_TO_PROG(sv.edicts); + PR_ExecuteProgram (ent->v.think); + return !ent->free; +} + +/* +================== +SV_Impact + +Two entities have touched, so run their touch functions +================== +*/ +void SV_Impact (edict_t *e1, edict_t *e2) +{ + int old_self, old_other; + + old_self = pr_global_struct->self; + old_other = pr_global_struct->other; + + pr_global_struct->time = sv.time; + if (e1->v.touch && e1->v.solid != SOLID_NOT) + { + pr_global_struct->self = EDICT_TO_PROG(e1); + pr_global_struct->other = EDICT_TO_PROG(e2); + PR_ExecuteProgram (e1->v.touch); + } + + if (e2->v.touch && e2->v.solid != SOLID_NOT) + { + pr_global_struct->self = EDICT_TO_PROG(e2); + pr_global_struct->other = EDICT_TO_PROG(e1); + PR_ExecuteProgram (e2->v.touch); + } + + pr_global_struct->self = old_self; + pr_global_struct->other = old_other; +} + + +/* +================== +ClipVelocity + +Slide off of the impacting object +returns the blocked flags (1 = floor, 2 = step / wall) +================== +*/ +#define STOP_EPSILON 0.1 + +int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) +{ + float backoff; + float change; + int i, blocked; + + blocked = 0; + if (normal[2] > 0) + blocked |= 1; // floor + if (!normal[2]) + blocked |= 2; // step + + backoff = DotProduct (in, normal) * overbounce; + + for (i=0 ; i<3 ; i++) + { + change = normal[i]*backoff; + out[i] = in[i] - change; + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + out[i] = 0; + } + + return blocked; +} + + +/* +============ +SV_FlyMove + +The basic solid body movement clip that slides along multiple planes +Returns the clipflags if the velocity was modified (hit something solid) +1 = floor +2 = wall / step +4 = dead stop +If steptrace is not NULL, the trace of any vertical wall hit will be stored +============ +*/ +#define MAX_CLIP_PLANES 5 +int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) +{ + int bumpcount, numbumps; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + vec3_t primal_velocity, original_velocity, new_velocity; + int i, j; + trace_t trace; + vec3_t end; + float time_left; + int blocked; + + numbumps = 4; + + blocked = 0; + VectorCopy (ent->v.velocity, original_velocity); + VectorCopy (ent->v.velocity, primal_velocity); + numplanes = 0; + + time_left = time; + + for (bumpcount=0 ; bumpcountv.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) + break; + + for (i=0 ; i<3 ; i++) + end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; + + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); + + if (trace.allsolid) + { // entity is trapped in another solid + VectorCopy (vec3_origin, ent->v.velocity); + return 3; + } + + if (trace.fraction > 0) + { // actually covered some distance + VectorCopy (trace.endpos, ent->v.origin); + VectorCopy (ent->v.velocity, original_velocity); + numplanes = 0; + } + + if (trace.fraction == 1) + break; // moved the entire distance + + if (!trace.ent) + Sys_Error ("SV_FlyMove: !trace.ent"); + + if (trace.plane.normal[2] > 0.7) + { + blocked |= 1; // floor + if (trace.ent->v.solid == SOLID_BSP) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = EDICT_TO_PROG(trace.ent); + } + } + if (!trace.plane.normal[2]) + { + blocked |= 2; // step + if (steptrace) + *steptrace = trace; // save for player extrafriction + } + +// +// run the impact function +// + SV_Impact (ent, trace.ent); + if (ent->free) + break; // removed by the impact function + + + time_left -= time_left * trace.fraction; + + // cliped to another plane + if (numplanes >= MAX_CLIP_PLANES) + { // this shouldn't really happen + VectorCopy (vec3_origin, ent->v.velocity); + return 3; + } + + VectorCopy (trace.plane.normal, planes[numplanes]); + numplanes++; + +// +// modify original_velocity so it parallels all of the clip planes +// + for (i=0 ; iv.velocity); + } + else + { // go along the crease + if (numplanes != 2) + { +// Con_Printf ("clip velocity, numplanes == %i\n",numplanes); + VectorCopy (vec3_origin, ent->v.velocity); + return 7; + } + CrossProduct (planes[0], planes[1], dir); + d = DotProduct (dir, ent->v.velocity); + VectorScale (dir, d, ent->v.velocity); + } + +// +// if original velocity is against the original velocity, stop dead +// to avoid tiny occilations in sloping corners +// + if (DotProduct (ent->v.velocity, primal_velocity) <= 0) + { + VectorCopy (vec3_origin, ent->v.velocity); + return blocked; + } + } + + return blocked; +} + + +/* +============ +SV_AddGravity + +============ +*/ +void SV_AddGravity (edict_t *ent) +{ + float ent_gravity; + +#ifdef QUAKE2 + if (ent->v.gravity) + ent_gravity = ent->v.gravity; + else + ent_gravity = 1.0; +#else + eval_t *val; + + val = GetEdictFieldValue(ent, "gravity"); + if (val && val->_float) + ent_gravity = val->_float; + else + ent_gravity = 1.0; +#endif + ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime; +} + + +/* +=============================================================================== + +PUSHMOVE + +=============================================================================== +*/ + +/* +============ +SV_PushEntity + +Does not change the entities velocity at all +============ +*/ +trace_t SV_PushEntity (edict_t *ent, vec3_t push) +{ + trace_t trace; + vec3_t end; + + VectorAdd (ent->v.origin, push, end); + + if (ent->v.movetype == MOVETYPE_FLYMISSILE) + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent); + else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT) + // only clip against bmodels + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent); + else + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); + + VectorCopy (trace.endpos, ent->v.origin); + SV_LinkEdict (ent, true); + + if (trace.ent) + SV_Impact (ent, trace.ent); + + return trace; +} + + +/* +============ +SV_PushMove + +============ +*/ +void SV_PushMove (edict_t *pusher, float movetime) +{ + int i, e; + edict_t *check, *block; + vec3_t mins, maxs, move; + vec3_t entorig, pushorig; + int num_moved; + edict_t *moved_edict[MAX_EDICTS]; + vec3_t moved_from[MAX_EDICTS]; + + if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) + { + pusher->v.ltime += movetime; + return; + } + + for (i=0 ; i<3 ; i++) + { + move[i] = pusher->v.velocity[i] * movetime; + mins[i] = pusher->v.absmin[i] + move[i]; + maxs[i] = pusher->v.absmax[i] + move[i]; + } + + VectorCopy (pusher->v.origin, pushorig); + +// move the pusher to it's final position + + VectorAdd (pusher->v.origin, move, pusher->v.origin); + pusher->v.ltime += movetime; + SV_LinkEdict (pusher, false); + + +// see if any solid entities are inside the final position + num_moved = 0; + check = NEXT_EDICT(sv.edicts); + for (e=1 ; efree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE +#ifdef QUAKE2 + || check->v.movetype == MOVETYPE_FOLLOW +#endif + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + // if the entity is standing on the pusher, it will definately be moved + if ( ! ( ((int)check->v.flags & FL_ONGROUND) + && PROG_TO_EDICT(check->v.groundentity) == pusher) ) + { + if ( check->v.absmin[0] >= maxs[0] + || check->v.absmin[1] >= maxs[1] + || check->v.absmin[2] >= maxs[2] + || check->v.absmax[0] <= mins[0] + || check->v.absmax[1] <= mins[1] + || check->v.absmax[2] <= mins[2] ) + continue; + + // see if the ent's bbox is inside the pusher's final position + if (!SV_TestEntityPosition (check)) + continue; + } + + // remove the onground flag for non-players + if (check->v.movetype != MOVETYPE_WALK) + check->v.flags = (int)check->v.flags & ~FL_ONGROUND; + + VectorCopy (check->v.origin, entorig); + VectorCopy (check->v.origin, moved_from[num_moved]); + moved_edict[num_moved] = check; + num_moved++; + + // try moving the contacted entity + pusher->v.solid = SOLID_NOT; + SV_PushEntity (check, move); + pusher->v.solid = SOLID_BSP; + + // if it is still inside the pusher, block + block = SV_TestEntityPosition (check); + if (block) + { // fail the move + if (check->v.mins[0] == check->v.maxs[0]) + continue; + if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) + { // corpse + check->v.mins[0] = check->v.mins[1] = 0; + VectorCopy (check->v.mins, check->v.maxs); + continue; + } + + VectorCopy (entorig, check->v.origin); + SV_LinkEdict (check, true); + + VectorCopy (pushorig, pusher->v.origin); + SV_LinkEdict (pusher, false); + pusher->v.ltime -= movetime; + + // if the pusher has a "blocked" function, call it + // otherwise, just stay in place until the obstacle is gone + if (pusher->v.blocked) + { + pr_global_struct->self = EDICT_TO_PROG(pusher); + pr_global_struct->other = EDICT_TO_PROG(check); + PR_ExecuteProgram (pusher->v.blocked); + } + + // move back any entities we already moved + for (i=0 ; iv.origin); + SV_LinkEdict (moved_edict[i], false); + } + return; + } + } + + +} + +#ifdef QUAKE2 +/* +============ +SV_PushRotate + +============ +*/ +void SV_PushRotate (edict_t *pusher, float movetime) +{ + int i, e; + edict_t *check, *block; + vec3_t move, a, amove; + vec3_t entorig, pushorig; + int num_moved; + edict_t *moved_edict[MAX_EDICTS]; + vec3_t moved_from[MAX_EDICTS]; + vec3_t org, org2; + vec3_t forward, right, up; + + if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2]) + { + pusher->v.ltime += movetime; + return; + } + + for (i=0 ; i<3 ; i++) + amove[i] = pusher->v.avelocity[i] * movetime; + + VectorSubtract (vec3_origin, amove, a); + AngleVectors (a, forward, right, up); + + VectorCopy (pusher->v.angles, pushorig); + +// move the pusher to it's final position + + VectorAdd (pusher->v.angles, amove, pusher->v.angles); + pusher->v.ltime += movetime; + SV_LinkEdict (pusher, false); + + +// see if any solid entities are inside the final position + num_moved = 0; + check = NEXT_EDICT(sv.edicts); + for (e=1 ; efree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + // if the entity is standing on the pusher, it will definately be moved + if ( ! ( ((int)check->v.flags & FL_ONGROUND) + && PROG_TO_EDICT(check->v.groundentity) == pusher) ) + { + if ( check->v.absmin[0] >= pusher->v.absmax[0] + || check->v.absmin[1] >= pusher->v.absmax[1] + || check->v.absmin[2] >= pusher->v.absmax[2] + || check->v.absmax[0] <= pusher->v.absmin[0] + || check->v.absmax[1] <= pusher->v.absmin[1] + || check->v.absmax[2] <= pusher->v.absmin[2] ) + continue; + + // see if the ent's bbox is inside the pusher's final position + if (!SV_TestEntityPosition (check)) + continue; + } + + // remove the onground flag for non-players + if (check->v.movetype != MOVETYPE_WALK) + check->v.flags = (int)check->v.flags & ~FL_ONGROUND; + + VectorCopy (check->v.origin, entorig); + VectorCopy (check->v.origin, moved_from[num_moved]); + moved_edict[num_moved] = check; + num_moved++; + + // calculate destination position + VectorSubtract (check->v.origin, pusher->v.origin, org); + org2[0] = DotProduct (org, forward); + org2[1] = -DotProduct (org, right); + org2[2] = DotProduct (org, up); + VectorSubtract (org2, org, move); + + // try moving the contacted entity + pusher->v.solid = SOLID_NOT; + SV_PushEntity (check, move); + pusher->v.solid = SOLID_BSP; + + // if it is still inside the pusher, block + block = SV_TestEntityPosition (check); + if (block) + { // fail the move + if (check->v.mins[0] == check->v.maxs[0]) + continue; + if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) + { // corpse + check->v.mins[0] = check->v.mins[1] = 0; + VectorCopy (check->v.mins, check->v.maxs); + continue; + } + + VectorCopy (entorig, check->v.origin); + SV_LinkEdict (check, true); + + VectorCopy (pushorig, pusher->v.angles); + SV_LinkEdict (pusher, false); + pusher->v.ltime -= movetime; + + // if the pusher has a "blocked" function, call it + // otherwise, just stay in place until the obstacle is gone + if (pusher->v.blocked) + { + pr_global_struct->self = EDICT_TO_PROG(pusher); + pr_global_struct->other = EDICT_TO_PROG(check); + PR_ExecuteProgram (pusher->v.blocked); + } + + // move back any entities we already moved + for (i=0 ; iv.origin); + VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); + SV_LinkEdict (moved_edict[i], false); + } + return; + } + else + { + VectorAdd (check->v.angles, amove, check->v.angles); + } + } + + +} +#endif + +/* +================ +SV_Physics_Pusher + +================ +*/ +void SV_Physics_Pusher (edict_t *ent) +{ + float thinktime; + float oldltime; + float movetime; + + oldltime = ent->v.ltime; + + thinktime = ent->v.nextthink; + if (thinktime < ent->v.ltime + host_frametime) + { + movetime = thinktime - ent->v.ltime; + if (movetime < 0) + movetime = 0; + } + else + movetime = host_frametime; + + if (movetime) + { +#ifdef QUAKE2 + if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2]) + SV_PushRotate (ent, movetime); + else +#endif + SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked + } + + if (thinktime > oldltime && thinktime <= ent->v.ltime) + { + ent->v.nextthink = 0; + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + pr_global_struct->other = EDICT_TO_PROG(sv.edicts); + PR_ExecuteProgram (ent->v.think); + if (ent->free) + return; + } + +} + + +/* +=============================================================================== + +CLIENT MOVEMENT + +=============================================================================== +*/ + +/* +============= +SV_CheckStuck + +This is a big hack to try and fix the rare case of getting stuck in the world +clipping hull. +============= +*/ +void SV_CheckStuck (edict_t *ent) +{ + int i, j; + int z; + vec3_t org; + + if (!SV_TestEntityPosition(ent)) + { + VectorCopy (ent->v.origin, ent->v.oldorigin); + return; + } + + VectorCopy (ent->v.origin, org); + VectorCopy (ent->v.oldorigin, ent->v.origin); + if (!SV_TestEntityPosition(ent)) + { + Con_DPrintf ("Unstuck.\n"); + SV_LinkEdict (ent, true); + return; + } + + for (z=0 ; z< 18 ; z++) + for (i=-1 ; i <= 1 ; i++) + for (j=-1 ; j <= 1 ; j++) + { + ent->v.origin[0] = org[0] + i; + ent->v.origin[1] = org[1] + j; + ent->v.origin[2] = org[2] + z; + if (!SV_TestEntityPosition(ent)) + { + Con_DPrintf ("Unstuck.\n"); + SV_LinkEdict (ent, true); + return; + } + } + + VectorCopy (org, ent->v.origin); + Con_DPrintf ("player is stuck.\n"); +} + + +/* +============= +SV_CheckWater +============= +*/ +qboolean SV_CheckWater (edict_t *ent) +{ + vec3_t point; + int cont; +#ifdef QUAKE2 + int truecont; +#endif + + point[0] = ent->v.origin[0]; + point[1] = ent->v.origin[1]; + point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; + + ent->v.waterlevel = 0; + ent->v.watertype = CONTENTS_EMPTY; + cont = SV_PointContents (point); + if (cont <= CONTENTS_WATER) + { +#ifdef QUAKE2 + truecont = SV_TruePointContents (point); +#endif + ent->v.watertype = cont; + ent->v.waterlevel = 1; + point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; + cont = SV_PointContents (point); + if (cont <= CONTENTS_WATER) + { + ent->v.waterlevel = 2; + point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; + cont = SV_PointContents (point); + if (cont <= CONTENTS_WATER) + ent->v.waterlevel = 3; + } +#ifdef QUAKE2 + if (truecont <= CONTENTS_CURRENT_0 && truecont >= CONTENTS_CURRENT_DOWN) + { + static vec3_t current_table[] = + { + {1, 0, 0}, + {0, 1, 0}, + {-1, 0, 0}, + {0, -1, 0}, + {0, 0, 1}, + {0, 0, -1} + }; + + VectorMA (ent->v.basevelocity, 150.0*ent->v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->v.basevelocity); + } +#endif + } + + return ent->v.waterlevel > 1; +} + +/* +============ +SV_WallFriction + +============ +*/ +void SV_WallFriction (edict_t *ent, trace_t *trace) +{ + vec3_t forward, right, up; + float d, i; + vec3_t into, side; + + AngleVectors (ent->v.v_angle, forward, right, up); + d = DotProduct (trace->plane.normal, forward); + + d += 0.5; + if (d >= 0) + return; + +// cut the tangential velocity + i = DotProduct (trace->plane.normal, ent->v.velocity); + VectorScale (trace->plane.normal, i, into); + VectorSubtract (ent->v.velocity, into, side); + + ent->v.velocity[0] = side[0] * (1 + d); + ent->v.velocity[1] = side[1] * (1 + d); +} + +/* +===================== +SV_TryUnstick + +Player has come to a dead stop, possibly due to the problem with limited +float precision at some angle joins in the BSP hull. + +Try fixing by pushing one pixel in each direction. + +This is a hack, but in the interest of good gameplay... +====================== +*/ +int SV_TryUnstick (edict_t *ent, vec3_t oldvel) +{ + int i; + vec3_t oldorg; + vec3_t dir; + int clip; + trace_t steptrace; + + VectorCopy (ent->v.origin, oldorg); + VectorCopy (vec3_origin, dir); + + for (i=0 ; i<8 ; i++) + { +// try pushing a little in an axial direction + switch (i) + { + case 0: dir[0] = 2; dir[1] = 0; break; + case 1: dir[0] = 0; dir[1] = 2; break; + case 2: dir[0] = -2; dir[1] = 0; break; + case 3: dir[0] = 0; dir[1] = -2; break; + case 4: dir[0] = 2; dir[1] = 2; break; + case 5: dir[0] = -2; dir[1] = 2; break; + case 6: dir[0] = 2; dir[1] = -2; break; + case 7: dir[0] = -2; dir[1] = -2; break; + } + + SV_PushEntity (ent, dir); + +// retry the original move + ent->v.velocity[0] = oldvel[0]; + ent->v. velocity[1] = oldvel[1]; + ent->v. velocity[2] = 0; + clip = SV_FlyMove (ent, 0.1, &steptrace); + + if ( fabs(oldorg[1] - ent->v.origin[1]) > 4 + || fabs(oldorg[0] - ent->v.origin[0]) > 4 ) + { +//Con_DPrintf ("unstuck!\n"); + return clip; + } + +// go back to the original pos and try again + VectorCopy (oldorg, ent->v.origin); + } + + VectorCopy (vec3_origin, ent->v.velocity); + return 7; // still not moving +} + +/* +===================== +SV_WalkMove + +Only used by players +====================== +*/ +#define STEPSIZE 18 +void SV_WalkMove (edict_t *ent) +{ + vec3_t upmove, downmove; + vec3_t oldorg, oldvel; + vec3_t nosteporg, nostepvel; + int clip; + int oldonground; + trace_t steptrace, downtrace; + +// +// do a regular slide move unless it looks like you ran into a step +// + oldonground = (int)ent->v.flags & FL_ONGROUND; + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + + VectorCopy (ent->v.origin, oldorg); + VectorCopy (ent->v.velocity, oldvel); + + clip = SV_FlyMove (ent, host_frametime, &steptrace); + + if ( !(clip & 2) ) + return; // move didn't block on a step + + if (!oldonground && ent->v.waterlevel == 0) + return; // don't stair up while jumping + + if (ent->v.movetype != MOVETYPE_WALK) + return; // gibbed by a trigger + + if (sv_nostep.value) + return; + + if ( (int)sv_player->v.flags & FL_WATERJUMP ) + return; + + VectorCopy (ent->v.origin, nosteporg); + VectorCopy (ent->v.velocity, nostepvel); + +// +// try moving up and forward to go up a step +// + VectorCopy (oldorg, ent->v.origin); // back to start pos + + VectorCopy (vec3_origin, upmove); + VectorCopy (vec3_origin, downmove); + upmove[2] = STEPSIZE; + downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; + +// move up + SV_PushEntity (ent, upmove); // FIXME: don't link? + +// move forward + ent->v.velocity[0] = oldvel[0]; + ent->v. velocity[1] = oldvel[1]; + ent->v. velocity[2] = 0; + clip = SV_FlyMove (ent, host_frametime, &steptrace); + +// check for stuckness, possibly due to the limited precision of floats +// in the clipping hulls + if (clip) + { + if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 + && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 ) + { // stepping up didn't make any progress + clip = SV_TryUnstick (ent, oldvel); + } + } + +// extra friction based on view angle + if ( clip & 2 ) + SV_WallFriction (ent, &steptrace); + +// move down + downtrace = SV_PushEntity (ent, downmove); // FIXME: don't link? + + if (downtrace.plane.normal[2] > 0.7) + { + if (ent->v.solid == SOLID_BSP) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); + } + } + else + { +// if the push down didn't end up on good ground, use the move without +// the step up. This happens near wall / slope combinations, and can +// cause the player to hop up higher on a slope too steep to climb + VectorCopy (nosteporg, ent->v.origin); + VectorCopy (nostepvel, ent->v.velocity); + } +} + + +/* +================ +SV_Physics_Client + +Player character actions +================ +*/ +void SV_Physics_Client (edict_t *ent, int num) +{ + if ( ! svs.clients[num-1].active ) + return; // unconnected slot + +// +// call standard client pre-think +// + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + PR_ExecuteProgram (pr_global_struct->PlayerPreThink); + +// +// do a move +// + SV_CheckVelocity (ent); + +// +// decide which move function to call +// + switch ((int)ent->v.movetype) + { + case MOVETYPE_NONE: + if (!SV_RunThink (ent)) + return; + break; + + case MOVETYPE_WALK: + if (!SV_RunThink (ent)) + return; + if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) + SV_AddGravity (ent); + SV_CheckStuck (ent); +#ifdef QUAKE2 + VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); +#endif + SV_WalkMove (ent); + +#ifdef QUAKE2 + VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); +#endif + break; + + case MOVETYPE_TOSS: + case MOVETYPE_BOUNCE: + SV_Physics_Toss (ent); + break; + + case MOVETYPE_FLY: + if (!SV_RunThink (ent)) + return; + SV_FlyMove (ent, host_frametime, NULL); + break; + + case MOVETYPE_NOCLIP: + if (!SV_RunThink (ent)) + return; + VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); + break; + + default: + Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); + } + +// +// call standard player post-think +// + SV_LinkEdict (ent, true); + + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + PR_ExecuteProgram (pr_global_struct->PlayerPostThink); +} + +//============================================================================ + +/* +============= +SV_Physics_None + +Non moving objects can only think +============= +*/ +void SV_Physics_None (edict_t *ent) +{ +// regular thinking + SV_RunThink (ent); +} + +#ifdef QUAKE2 +/* +============= +SV_Physics_Follow + +Entities that are "stuck" to another entity +============= +*/ +void SV_Physics_Follow (edict_t *ent) +{ +// regular thinking + SV_RunThink (ent); + VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin); + SV_LinkEdict (ent, true); +} +#endif + +/* +============= +SV_Physics_Noclip + +A moving object that doesn't obey physics +============= +*/ +void SV_Physics_Noclip (edict_t *ent) +{ +// regular thinking + if (!SV_RunThink (ent)) + return; + + VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); + + SV_LinkEdict (ent, false); +} + +/* +============================================================================== + +TOSS / BOUNCE + +============================================================================== +*/ + +/* +============= +SV_CheckWaterTransition + +============= +*/ +void SV_CheckWaterTransition (edict_t *ent) +{ + int cont; +#ifdef QUAKE2 + vec3_t point; + + point[0] = ent->v.origin[0]; + point[1] = ent->v.origin[1]; + point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; + cont = SV_PointContents (point); +#else + cont = SV_PointContents (ent->v.origin); +#endif + if (!ent->v.watertype) + { // just spawned here + ent->v.watertype = cont; + ent->v.waterlevel = 1; + return; + } + + if (cont <= CONTENTS_WATER) + { + if (ent->v.watertype == CONTENTS_EMPTY) + { // just crossed into water + SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + } + ent->v.watertype = cont; + ent->v.waterlevel = 1; + } + else + { + if (ent->v.watertype != CONTENTS_EMPTY) + { // just crossed into water + SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + } + ent->v.watertype = CONTENTS_EMPTY; + ent->v.waterlevel = cont; + } +} + +/* +============= +SV_Physics_Toss + +Toss, bounce, and fly movement. When onground, do nothing. +============= +*/ +void SV_Physics_Toss (edict_t *ent) +{ + trace_t trace; + vec3_t move; + float backoff; +#ifdef QUAKE2 + edict_t *groundentity; + + groundentity = PROG_TO_EDICT(ent->v.groundentity); + if ((int)groundentity->v.flags & FL_CONVEYOR) + VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity); + else + VectorCopy(vec_origin, ent->v.basevelocity); + SV_CheckWater (ent); +#endif + // regular thinking + if (!SV_RunThink (ent)) + return; + +#ifdef QUAKE2 + if (ent->v.velocity[2] > 0) + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + + if ( ((int)ent->v.flags & FL_ONGROUND) ) +//@@ + if (VectorCompare(ent->v.basevelocity, vec_origin)) + return; + + SV_CheckVelocity (ent); + +// add gravity + if (! ((int)ent->v.flags & FL_ONGROUND) + && ent->v.movetype != MOVETYPE_FLY + && ent->v.movetype != MOVETYPE_BOUNCEMISSILE + && ent->v.movetype != MOVETYPE_FLYMISSILE) + SV_AddGravity (ent); + +#else +// if onground, return without moving + if ( ((int)ent->v.flags & FL_ONGROUND) ) + return; + + SV_CheckVelocity (ent); + +// add gravity + if (ent->v.movetype != MOVETYPE_FLY + && ent->v.movetype != MOVETYPE_FLYMISSILE) + SV_AddGravity (ent); +#endif + +// move angles + VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + +// move origin +#ifdef QUAKE2 + VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); +#endif + VectorScale (ent->v.velocity, host_frametime, move); + trace = SV_PushEntity (ent, move); +#ifdef QUAKE2 + VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); +#endif + if (trace.fraction == 1) + return; + if (ent->free) + return; + + if (ent->v.movetype == MOVETYPE_BOUNCE) + backoff = 1.5; +#ifdef QUAKE2 + else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE) + backoff = 2.0; +#endif + else + backoff = 1; + + ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); + +// stop if on ground + if (trace.plane.normal[2] > 0.7) + { +#ifdef QUAKE2 + if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE)) +#else + if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) +#endif + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = EDICT_TO_PROG(trace.ent); + VectorCopy (vec3_origin, ent->v.velocity); + VectorCopy (vec3_origin, ent->v.avelocity); + } + } + +// check for in water + SV_CheckWaterTransition (ent); +} + +/* +=============================================================================== + +STEPPING MOVEMENT + +=============================================================================== +*/ + +/* +============= +SV_Physics_Step + +Monsters freefall when they don't have a ground entity, otherwise +all movement is done with discrete steps. + +This is also used for objects that have become still on the ground, but +will fall if the floor is pulled out from under them. +============= +*/ +#ifdef QUAKE2 +void SV_Physics_Step (edict_t *ent) +{ + qboolean wasonground; + qboolean inwater; + qboolean hitsound = false; + float *vel; + float speed, newspeed, control; + float friction; + edict_t *groundentity; + + groundentity = PROG_TO_EDICT(ent->v.groundentity); + if ((int)groundentity->v.flags & FL_CONVEYOR) + VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity); + else + VectorCopy(vec_origin, ent->v.basevelocity); +//@@ + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + PF_WaterMove(); + + SV_CheckVelocity (ent); + + wasonground = (int)ent->v.flags & FL_ONGROUND; +// ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + + // add gravity except: + // flying monsters + // swimming monsters who are in the water + inwater = SV_CheckWater(ent); + if (! wasonground) + if (!((int)ent->v.flags & FL_FLY)) + if (!(((int)ent->v.flags & FL_SWIM) && (ent->v.waterlevel > 0))) + { + if (ent->v.velocity[2] < sv_gravity.value*-0.1) + hitsound = true; + if (!inwater) + SV_AddGravity (ent); + } + + if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin)) + { + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + // apply friction + // let dead monsters who aren't completely onground slide + if (wasonground) + if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent))) + { + vel = ent->v.velocity; + speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); + if (speed) + { + friction = sv_friction.value; + + control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; + newspeed = speed - host_frametime*control*friction; + + if (newspeed < 0) + newspeed = 0; + newspeed /= speed; + + vel[0] = vel[0] * newspeed; + vel[1] = vel[1] * newspeed; + } + } + + VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); + SV_FlyMove (ent, host_frametime, NULL); + VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); + + // determine if it's on solid ground at all + { + vec3_t mins, maxs, point; + int x, y; + + VectorAdd (ent->v.origin, ent->v.mins, mins); + VectorAdd (ent->v.origin, ent->v.maxs, maxs); + + point[2] = mins[2] - 1; + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + point[0] = x ? maxs[0] : mins[0]; + point[1] = y ? maxs[1] : mins[1]; + if (SV_PointContents (point) == CONTENTS_SOLID) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + break; + } + } + + } + + SV_LinkEdict (ent, true); + + if ((int)ent->v.flags & FL_ONGROUND) + if (!wasonground) + if (hitsound) + SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + } + +// regular thinking + SV_RunThink (ent); + SV_CheckWaterTransition (ent); +} +#else +void SV_Physics_Step (edict_t *ent) +{ + qboolean hitsound; + +// freefall if not onground + if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) + { + if (ent->v.velocity[2] < sv_gravity.value*-0.1) + hitsound = true; + else + hitsound = false; + + SV_AddGravity (ent); + SV_CheckVelocity (ent); + SV_FlyMove (ent, host_frametime, NULL); + SV_LinkEdict (ent, true); + + if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground + { + if (hitsound) + SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + } + } + +// regular thinking + SV_RunThink (ent); + + SV_CheckWaterTransition (ent); +} +#endif + +//============================================================================ + +/* +================ +SV_Physics + +================ +*/ +void SV_Physics (void) +{ + int i; + edict_t *ent; + +// let the progs know that a new frame has started + pr_global_struct->self = EDICT_TO_PROG(sv.edicts); + pr_global_struct->other = EDICT_TO_PROG(sv.edicts); + pr_global_struct->time = sv.time; + PR_ExecuteProgram (pr_global_struct->StartFrame); + +//SV_CheckAllEnts (); + +// +// treat each object in turn +// + ent = sv.edicts; + for (i=0 ; ifree) + continue; + + if (pr_global_struct->force_retouch) + { + SV_LinkEdict (ent, true); // force retouch even for stationary + } + + if (i > 0 && i <= svs.maxclients) + SV_Physics_Client (ent, i); + else if (ent->v.movetype == MOVETYPE_PUSH) + SV_Physics_Pusher (ent); + else if (ent->v.movetype == MOVETYPE_NONE) + SV_Physics_None (ent); +#ifdef QUAKE2 + else if (ent->v.movetype == MOVETYPE_FOLLOW) + SV_Physics_Follow (ent); +#endif + else if (ent->v.movetype == MOVETYPE_NOCLIP) + SV_Physics_Noclip (ent); + else if (ent->v.movetype == MOVETYPE_STEP) + SV_Physics_Step (ent); + else if (ent->v.movetype == MOVETYPE_TOSS + || ent->v.movetype == MOVETYPE_BOUNCE +#ifdef QUAKE2 + || ent->v.movetype == MOVETYPE_BOUNCEMISSILE +#endif + || ent->v.movetype == MOVETYPE_FLY + || ent->v.movetype == MOVETYPE_FLYMISSILE) + SV_Physics_Toss (ent); + else + Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); + } + + if (pr_global_struct->force_retouch) + pr_global_struct->force_retouch--; + + sv.time += host_frametime; +} + + +#ifdef QUAKE2 +trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) +{ + edict_t tempent, *tent; + trace_t trace; + vec3_t move; + vec3_t end; + double save_frametime; +// extern particle_t *active_particles, *free_particles; +// particle_t *p; + + + save_frametime = host_frametime; + host_frametime = 0.05; + + memcpy(&tempent, ent, sizeof(edict_t)); + tent = &tempent; + + while (1) + { + SV_CheckVelocity (tent); + SV_AddGravity (tent); + VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles); + VectorScale (tent->v.velocity, host_frametime, move); + VectorAdd (tent->v.origin, move, end); + trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent); + VectorCopy (trace.endpos, tent->v.origin); + +// p = free_particles; +// if (p) +// { +// free_particles = p->next; +// p->next = active_particles; +// active_particles = p; +// +// p->die = 256; +// p->color = 15; +// p->type = pt_static; +// VectorCopy (vec3_origin, p->vel); +// VectorCopy (tent->v.origin, p->org); +// } + + if (trace.ent) + if (trace.ent != ignore) + break; + } +// p->color = 224; + host_frametime = save_frametime; + return trace; +} +#endif diff --git a/WinQuake/sv_user.c b/WinQuake/sv_user.c index 1163949..42c0329 100644 --- a/WinQuake/sv_user.c +++ b/WinQuake/sv_user.c @@ -1,629 +1,629 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_user.c -- server code for moving users - -#include "quakedef.h" - -edict_t *sv_player; - -extern cvar_t sv_friction; -cvar_t sv_edgefriction = {"edgefriction", "2"}; -extern cvar_t sv_stopspeed; - -static vec3_t forward, right, up; - -vec3_t wishdir; -float wishspeed; - -// world -float *angles; -float *origin; -float *velocity; - -qboolean onground; - -usercmd_t cmd; - -cvar_t sv_idealpitchscale = {"sv_idealpitchscale","0.8"}; - - -/* -=============== -SV_SetIdealPitch -=============== -*/ -#define MAX_FORWARD 6 -void SV_SetIdealPitch (void) -{ - float angleval, sinval, cosval; - trace_t tr; - vec3_t top, bottom; - float z[MAX_FORWARD]; - int i, j; - int step, dir, steps; - - if (!((int)sv_player->v.flags & FL_ONGROUND)) - return; - - angleval = sv_player->v.angles[YAW] * M_PI*2 / 360; - sinval = sin(angleval); - cosval = cos(angleval); - - for (i=0 ; iv.origin[0] + cosval*(i+3)*12; - top[1] = sv_player->v.origin[1] + sinval*(i+3)*12; - top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2]; - - bottom[0] = top[0]; - bottom[1] = top[1]; - bottom[2] = top[2] - 160; - - tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player); - if (tr.allsolid) - return; // looking at a wall, leave ideal the way is was - - if (tr.fraction == 1) - return; // near a dropoff - - z[i] = top[2] + tr.fraction*(bottom[2]-top[2]); - } - - dir = 0; - steps = 0; - for (j=1 ; j -ON_EPSILON && step < ON_EPSILON) - continue; - - if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) ) - return; // mixed changes - - steps++; - dir = step; - } - - if (!dir) - { - sv_player->v.idealpitch = 0; - return; - } - - if (steps < 2) - return; - sv_player->v.idealpitch = -dir * sv_idealpitchscale.value; -} - - -/* -================== -SV_UserFriction - -================== -*/ -void SV_UserFriction (void) -{ - float *vel; - float speed, newspeed, control; - vec3_t start, stop; - float friction; - trace_t trace; - - vel = velocity; - - speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); - if (!speed) - return; - -// if the leading edge is over a dropoff, increase friction - start[0] = stop[0] = origin[0] + vel[0]/speed*16; - start[1] = stop[1] = origin[1] + vel[1]/speed*16; - start[2] = origin[2] + sv_player->v.mins[2]; - stop[2] = start[2] - 34; - - trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player); - - if (trace.fraction == 1.0) - friction = sv_friction.value*sv_edgefriction.value; - else - friction = sv_friction.value; - -// apply friction - control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; - newspeed = speed - host_frametime*control*friction; - - if (newspeed < 0) - newspeed = 0; - newspeed /= speed; - - vel[0] = vel[0] * newspeed; - vel[1] = vel[1] * newspeed; - vel[2] = vel[2] * newspeed; -} - -/* -============== -SV_Accelerate -============== -*/ -cvar_t sv_maxspeed = {"sv_maxspeed", "320", false, true}; -cvar_t sv_accelerate = {"sv_accelerate", "10"}; -#if 0 -void SV_Accelerate (vec3_t wishvel) -{ - int i; - float addspeed, accelspeed; - vec3_t pushvec; - - if (wishspeed == 0) - return; - - VectorSubtract (wishvel, velocity, pushvec); - addspeed = VectorNormalize (pushvec); - - accelspeed = sv_accelerate.value*host_frametime*addspeed; - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed*pushvec[i]; -} -#endif -void SV_Accelerate (void) -{ - int i; - float addspeed, accelspeed, currentspeed; - - currentspeed = DotProduct (velocity, wishdir); - addspeed = wishspeed - currentspeed; - if (addspeed <= 0) - return; - accelspeed = sv_accelerate.value*host_frametime*wishspeed; - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed*wishdir[i]; -} - -void SV_AirAccelerate (vec3_t wishveloc) -{ - int i; - float addspeed, wishspd, accelspeed, currentspeed; - - wishspd = VectorNormalize (wishveloc); - if (wishspd > 30) - wishspd = 30; - currentspeed = DotProduct (velocity, wishveloc); - addspeed = wishspd - currentspeed; - if (addspeed <= 0) - return; -// accelspeed = sv_accelerate.value * host_frametime; - accelspeed = sv_accelerate.value*wishspeed * host_frametime; - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed*wishveloc[i]; -} - - -void DropPunchAngle (void) -{ - float len; - - len = VectorNormalize (sv_player->v.punchangle); - - len -= 10*host_frametime; - if (len < 0) - len = 0; - VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle); -} - -/* -=================== -SV_WaterMove - -=================== -*/ -void SV_WaterMove (void) -{ - int i; - vec3_t wishvel; - float speed, newspeed, wishspeed, addspeed, accelspeed; - -// -// user intentions -// - AngleVectors (sv_player->v.v_angle, forward, right, up); - - for (i=0 ; i<3 ; i++) - wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove; - - if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove) - wishvel[2] -= 60; // drift towards bottom - else - wishvel[2] += cmd.upmove; - - wishspeed = Length(wishvel); - if (wishspeed > sv_maxspeed.value) - { - VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); - wishspeed = sv_maxspeed.value; - } - wishspeed *= 0.7; - -// -// water friction -// - speed = Length (velocity); - if (speed) - { - newspeed = speed - host_frametime * speed * sv_friction.value; - if (newspeed < 0) - newspeed = 0; - VectorScale (velocity, newspeed/speed, velocity); - } - else - newspeed = 0; - -// -// water acceleration -// - if (!wishspeed) - return; - - addspeed = wishspeed - newspeed; - if (addspeed <= 0) - return; - - VectorNormalize (wishvel); - accelspeed = sv_accelerate.value * wishspeed * host_frametime; - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i=0 ; i<3 ; i++) - velocity[i] += accelspeed * wishvel[i]; -} - -void SV_WaterJump (void) -{ - if (sv.time > sv_player->v.teleport_time - || !sv_player->v.waterlevel) - { - sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP; - sv_player->v.teleport_time = 0; - } - sv_player->v.velocity[0] = sv_player->v.movedir[0]; - sv_player->v.velocity[1] = sv_player->v.movedir[1]; -} - - -/* -=================== -SV_AirMove - -=================== -*/ -void SV_AirMove (void) -{ - int i; - vec3_t wishvel; - float fmove, smove; - - AngleVectors (sv_player->v.angles, forward, right, up); - - fmove = cmd.forwardmove; - smove = cmd.sidemove; - -// hack to not let you back into teleporter - if (sv.time < sv_player->v.teleport_time && fmove < 0) - fmove = 0; - - for (i=0 ; i<3 ; i++) - wishvel[i] = forward[i]*fmove + right[i]*smove; - - if ( (int)sv_player->v.movetype != MOVETYPE_WALK) - wishvel[2] = cmd.upmove; - else - wishvel[2] = 0; - - VectorCopy (wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - if (wishspeed > sv_maxspeed.value) - { - VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); - wishspeed = sv_maxspeed.value; - } - - if ( sv_player->v.movetype == MOVETYPE_NOCLIP) - { // noclip - VectorCopy (wishvel, velocity); - } - else if ( onground ) - { - SV_UserFriction (); - SV_Accelerate (); - } - else - { // not on ground, so little effect on velocity - SV_AirAccelerate (wishvel); - } -} - -/* -=================== -SV_ClientThink - -the move fields specify an intended velocity in pix/sec -the angle fields specify an exact angular motion in degrees -=================== -*/ -void SV_ClientThink (void) -{ - vec3_t v_angle; - - if (sv_player->v.movetype == MOVETYPE_NONE) - return; - - onground = (int)sv_player->v.flags & FL_ONGROUND; - - origin = sv_player->v.origin; - velocity = sv_player->v.velocity; - - DropPunchAngle (); - -// -// if dead, behave differently -// - if (sv_player->v.health <= 0) - return; - -// -// angles -// show 1/3 the pitch angle and all the roll angle - cmd = host_client->cmd; - angles = sv_player->v.angles; - - VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle); - angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4; - if (!sv_player->v.fixangle) - { - angles[PITCH] = -v_angle[PITCH]/3; - angles[YAW] = v_angle[YAW]; - } - - if ( (int)sv_player->v.flags & FL_WATERJUMP ) - { - SV_WaterJump (); - return; - } -// -// walk -// - if ( (sv_player->v.waterlevel >= 2) - && (sv_player->v.movetype != MOVETYPE_NOCLIP) ) - { - SV_WaterMove (); - return; - } - - SV_AirMove (); -} - - -/* -=================== -SV_ReadClientMove -=================== -*/ -void SV_ReadClientMove (usercmd_t *move) -{ - int i; - vec3_t angle; - int bits; - -// read ping time - host_client->ping_times[host_client->num_pings%NUM_PING_TIMES] - = sv.time - MSG_ReadFloat (); - host_client->num_pings++; - -// read current angles - for (i=0 ; i<3 ; i++) - angle[i] = MSG_ReadAngle (); - - VectorCopy (angle, host_client->edict->v.v_angle); - -// read movement - move->forwardmove = MSG_ReadShort (); - move->sidemove = MSG_ReadShort (); - move->upmove = MSG_ReadShort (); - -// read buttons - bits = MSG_ReadByte (); - host_client->edict->v.button0 = bits & 1; - host_client->edict->v.button2 = (bits & 2)>>1; - - i = MSG_ReadByte (); - if (i) - host_client->edict->v.impulse = i; - -#ifdef QUAKE2 -// read light level - host_client->edict->v.light_level = MSG_ReadByte (); -#endif -} - -/* -=================== -SV_ReadClientMessage - -Returns false if the client should be killed -=================== -*/ -qboolean SV_ReadClientMessage (void) -{ - int ret; - int cmd; - char *s; - - do - { -nextmsg: - ret = NET_GetMessage (host_client->netconnection); - if (ret == -1) - { - Sys_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n"); - return false; - } - if (!ret) - return true; - - MSG_BeginReading (); - - while (1) - { - if (!host_client->active) - return false; // a command caused an error - - if (msg_badread) - { - Sys_Printf ("SV_ReadClientMessage: badread\n"); - return false; - } - - cmd = MSG_ReadChar (); - - switch (cmd) - { - case -1: - goto nextmsg; // end of message - - default: - Sys_Printf ("SV_ReadClientMessage: unknown command char\n"); - return false; - - case clc_nop: -// Sys_Printf ("clc_nop\n"); - break; - - case clc_stringcmd: - s = MSG_ReadString (); - if (host_client->privileged) - ret = 2; - else - ret = 0; - if (Q_strncasecmp(s, "status", 6) == 0) - ret = 1; - else if (Q_strncasecmp(s, "god", 3) == 0) - ret = 1; - else if (Q_strncasecmp(s, "notarget", 8) == 0) - ret = 1; - else if (Q_strncasecmp(s, "fly", 3) == 0) - ret = 1; - else if (Q_strncasecmp(s, "name", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "noclip", 6) == 0) - ret = 1; - else if (Q_strncasecmp(s, "say", 3) == 0) - ret = 1; - else if (Q_strncasecmp(s, "say_team", 8) == 0) - ret = 1; - else if (Q_strncasecmp(s, "tell", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "color", 5) == 0) - ret = 1; - else if (Q_strncasecmp(s, "kill", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "pause", 5) == 0) - ret = 1; - else if (Q_strncasecmp(s, "spawn", 5) == 0) - ret = 1; - else if (Q_strncasecmp(s, "begin", 5) == 0) - ret = 1; - else if (Q_strncasecmp(s, "prespawn", 8) == 0) - ret = 1; - else if (Q_strncasecmp(s, "kick", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "ping", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "give", 4) == 0) - ret = 1; - else if (Q_strncasecmp(s, "ban", 3) == 0) - ret = 1; - if (ret == 2) - Cbuf_InsertText (s); - else if (ret == 1) - Cmd_ExecuteString (s, src_client); - else - Con_DPrintf("%s tried to %s\n", host_client->name, s); - break; - - case clc_disconnect: -// Sys_Printf ("SV_ReadClientMessage: client disconnected\n"); - return false; - - case clc_move: - SV_ReadClientMove (&host_client->cmd); - break; - } - } - } while (ret == 1); - - return true; -} - - -/* -================== -SV_RunClients -================== -*/ -void SV_RunClients (void) -{ - int i; - - for (i=0, host_client = svs.clients ; iactive) - continue; - - sv_player = host_client->edict; - - if (!SV_ReadClientMessage ()) - { - SV_DropClient (false); // client misbehaved... - continue; - } - - if (!host_client->spawned) - { - // clear client movement until a new packet is received - memset (&host_client->cmd, 0, sizeof(host_client->cmd)); - continue; - } - -// always pause in single player if in console or menus - if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) - SV_ClientThink (); - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_user.c -- server code for moving users + +#include "quakedef.h" + +edict_t *sv_player; + +extern cvar_t sv_friction; +cvar_t sv_edgefriction = {"edgefriction", "2"}; +extern cvar_t sv_stopspeed; + +static vec3_t forward, right, up; + +vec3_t wishdir; +float wishspeed; + +// world +float *angles; +float *origin; +float *velocity; + +qboolean onground; + +usercmd_t cmd; + +cvar_t sv_idealpitchscale = {"sv_idealpitchscale","0.8"}; + + +/* +=============== +SV_SetIdealPitch +=============== +*/ +#define MAX_FORWARD 6 +void SV_SetIdealPitch (void) +{ + float angleval, sinval, cosval; + trace_t tr; + vec3_t top, bottom; + float z[MAX_FORWARD]; + int i, j; + int step, dir, steps; + + if (!((int)sv_player->v.flags & FL_ONGROUND)) + return; + + angleval = sv_player->v.angles[YAW] * M_PI*2 / 360; + sinval = sin(angleval); + cosval = cos(angleval); + + for (i=0 ; iv.origin[0] + cosval*(i+3)*12; + top[1] = sv_player->v.origin[1] + sinval*(i+3)*12; + top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2]; + + bottom[0] = top[0]; + bottom[1] = top[1]; + bottom[2] = top[2] - 160; + + tr = SV_Move (top, vec3_origin, vec3_origin, bottom, 1, sv_player); + if (tr.allsolid) + return; // looking at a wall, leave ideal the way is was + + if (tr.fraction == 1) + return; // near a dropoff + + z[i] = top[2] + tr.fraction*(bottom[2]-top[2]); + } + + dir = 0; + steps = 0; + for (j=1 ; j -ON_EPSILON && step < ON_EPSILON) + continue; + + if (dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON ) ) + return; // mixed changes + + steps++; + dir = step; + } + + if (!dir) + { + sv_player->v.idealpitch = 0; + return; + } + + if (steps < 2) + return; + sv_player->v.idealpitch = -dir * sv_idealpitchscale.value; +} + + +/* +================== +SV_UserFriction + +================== +*/ +void SV_UserFriction (void) +{ + float *vel; + float speed, newspeed, control; + vec3_t start, stop; + float friction; + trace_t trace; + + vel = velocity; + + speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); + if (!speed) + return; + +// if the leading edge is over a dropoff, increase friction + start[0] = stop[0] = origin[0] + vel[0]/speed*16; + start[1] = stop[1] = origin[1] + vel[1]/speed*16; + start[2] = origin[2] + sv_player->v.mins[2]; + stop[2] = start[2] - 34; + + trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player); + + if (trace.fraction == 1.0) + friction = sv_friction.value*sv_edgefriction.value; + else + friction = sv_friction.value; + +// apply friction + control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; + newspeed = speed - host_frametime*control*friction; + + if (newspeed < 0) + newspeed = 0; + newspeed /= speed; + + vel[0] = vel[0] * newspeed; + vel[1] = vel[1] * newspeed; + vel[2] = vel[2] * newspeed; +} + +/* +============== +SV_Accelerate +============== +*/ +cvar_t sv_maxspeed = {"sv_maxspeed", "320", false, true}; +cvar_t sv_accelerate = {"sv_accelerate", "10"}; +#if 0 +void SV_Accelerate (vec3_t wishvel) +{ + int i; + float addspeed, accelspeed; + vec3_t pushvec; + + if (wishspeed == 0) + return; + + VectorSubtract (wishvel, velocity, pushvec); + addspeed = VectorNormalize (pushvec); + + accelspeed = sv_accelerate.value*host_frametime*addspeed; + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i=0 ; i<3 ; i++) + velocity[i] += accelspeed*pushvec[i]; +} +#endif +void SV_Accelerate (void) +{ + int i; + float addspeed, accelspeed, currentspeed; + + currentspeed = DotProduct (velocity, wishdir); + addspeed = wishspeed - currentspeed; + if (addspeed <= 0) + return; + accelspeed = sv_accelerate.value*host_frametime*wishspeed; + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i=0 ; i<3 ; i++) + velocity[i] += accelspeed*wishdir[i]; +} + +void SV_AirAccelerate (vec3_t wishveloc) +{ + int i; + float addspeed, wishspd, accelspeed, currentspeed; + + wishspd = VectorNormalize (wishveloc); + if (wishspd > 30) + wishspd = 30; + currentspeed = DotProduct (velocity, wishveloc); + addspeed = wishspd - currentspeed; + if (addspeed <= 0) + return; +// accelspeed = sv_accelerate.value * host_frametime; + accelspeed = sv_accelerate.value*wishspeed * host_frametime; + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i=0 ; i<3 ; i++) + velocity[i] += accelspeed*wishveloc[i]; +} + + +void DropPunchAngle (void) +{ + float len; + + len = VectorNormalize (sv_player->v.punchangle); + + len -= 10*host_frametime; + if (len < 0) + len = 0; + VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle); +} + +/* +=================== +SV_WaterMove + +=================== +*/ +void SV_WaterMove (void) +{ + int i; + vec3_t wishvel; + float speed, newspeed, wishspeed, addspeed, accelspeed; + +// +// user intentions +// + AngleVectors (sv_player->v.v_angle, forward, right, up); + + for (i=0 ; i<3 ; i++) + wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove; + + if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove) + wishvel[2] -= 60; // drift towards bottom + else + wishvel[2] += cmd.upmove; + + wishspeed = Length(wishvel); + if (wishspeed > sv_maxspeed.value) + { + VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); + wishspeed = sv_maxspeed.value; + } + wishspeed *= 0.7; + +// +// water friction +// + speed = Length (velocity); + if (speed) + { + newspeed = speed - host_frametime * speed * sv_friction.value; + if (newspeed < 0) + newspeed = 0; + VectorScale (velocity, newspeed/speed, velocity); + } + else + newspeed = 0; + +// +// water acceleration +// + if (!wishspeed) + return; + + addspeed = wishspeed - newspeed; + if (addspeed <= 0) + return; + + VectorNormalize (wishvel); + accelspeed = sv_accelerate.value * wishspeed * host_frametime; + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i=0 ; i<3 ; i++) + velocity[i] += accelspeed * wishvel[i]; +} + +void SV_WaterJump (void) +{ + if (sv.time > sv_player->v.teleport_time + || !sv_player->v.waterlevel) + { + sv_player->v.flags = (int)sv_player->v.flags & ~FL_WATERJUMP; + sv_player->v.teleport_time = 0; + } + sv_player->v.velocity[0] = sv_player->v.movedir[0]; + sv_player->v.velocity[1] = sv_player->v.movedir[1]; +} + + +/* +=================== +SV_AirMove + +=================== +*/ +void SV_AirMove (void) +{ + int i; + vec3_t wishvel; + float fmove, smove; + + AngleVectors (sv_player->v.angles, forward, right, up); + + fmove = cmd.forwardmove; + smove = cmd.sidemove; + +// hack to not let you back into teleporter + if (sv.time < sv_player->v.teleport_time && fmove < 0) + fmove = 0; + + for (i=0 ; i<3 ; i++) + wishvel[i] = forward[i]*fmove + right[i]*smove; + + if ( (int)sv_player->v.movetype != MOVETYPE_WALK) + wishvel[2] = cmd.upmove; + else + wishvel[2] = 0; + + VectorCopy (wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + if (wishspeed > sv_maxspeed.value) + { + VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); + wishspeed = sv_maxspeed.value; + } + + if ( sv_player->v.movetype == MOVETYPE_NOCLIP) + { // noclip + VectorCopy (wishvel, velocity); + } + else if ( onground ) + { + SV_UserFriction (); + SV_Accelerate (); + } + else + { // not on ground, so little effect on velocity + SV_AirAccelerate (wishvel); + } +} + +/* +=================== +SV_ClientThink + +the move fields specify an intended velocity in pix/sec +the angle fields specify an exact angular motion in degrees +=================== +*/ +void SV_ClientThink (void) +{ + vec3_t v_angle; + + if (sv_player->v.movetype == MOVETYPE_NONE) + return; + + onground = (int)sv_player->v.flags & FL_ONGROUND; + + origin = sv_player->v.origin; + velocity = sv_player->v.velocity; + + DropPunchAngle (); + +// +// if dead, behave differently +// + if (sv_player->v.health <= 0) + return; + +// +// angles +// show 1/3 the pitch angle and all the roll angle + cmd = host_client->cmd; + angles = sv_player->v.angles; + + VectorAdd (sv_player->v.v_angle, sv_player->v.punchangle, v_angle); + angles[ROLL] = V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4; + if (!sv_player->v.fixangle) + { + angles[PITCH] = -v_angle[PITCH]/3; + angles[YAW] = v_angle[YAW]; + } + + if ( (int)sv_player->v.flags & FL_WATERJUMP ) + { + SV_WaterJump (); + return; + } +// +// walk +// + if ( (sv_player->v.waterlevel >= 2) + && (sv_player->v.movetype != MOVETYPE_NOCLIP) ) + { + SV_WaterMove (); + return; + } + + SV_AirMove (); +} + + +/* +=================== +SV_ReadClientMove +=================== +*/ +void SV_ReadClientMove (usercmd_t *move) +{ + int i; + vec3_t angle; + int bits; + +// read ping time + host_client->ping_times[host_client->num_pings%NUM_PING_TIMES] + = sv.time - MSG_ReadFloat (); + host_client->num_pings++; + +// read current angles + for (i=0 ; i<3 ; i++) + angle[i] = MSG_ReadAngle (); + + VectorCopy (angle, host_client->edict->v.v_angle); + +// read movement + move->forwardmove = MSG_ReadShort (); + move->sidemove = MSG_ReadShort (); + move->upmove = MSG_ReadShort (); + +// read buttons + bits = MSG_ReadByte (); + host_client->edict->v.button0 = bits & 1; + host_client->edict->v.button2 = (bits & 2)>>1; + + i = MSG_ReadByte (); + if (i) + host_client->edict->v.impulse = i; + +#ifdef QUAKE2 +// read light level + host_client->edict->v.light_level = MSG_ReadByte (); +#endif +} + +/* +=================== +SV_ReadClientMessage + +Returns false if the client should be killed +=================== +*/ +qboolean SV_ReadClientMessage (void) +{ + int ret; + int cmd; + char *s; + + do + { +nextmsg: + ret = NET_GetMessage (host_client->netconnection); + if (ret == -1) + { + Sys_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n"); + return false; + } + if (!ret) + return true; + + MSG_BeginReading (); + + while (1) + { + if (!host_client->active) + return false; // a command caused an error + + if (msg_badread) + { + Sys_Printf ("SV_ReadClientMessage: badread\n"); + return false; + } + + cmd = MSG_ReadChar (); + + switch (cmd) + { + case -1: + goto nextmsg; // end of message + + default: + Sys_Printf ("SV_ReadClientMessage: unknown command char\n"); + return false; + + case clc_nop: +// Sys_Printf ("clc_nop\n"); + break; + + case clc_stringcmd: + s = MSG_ReadString (); + if (host_client->privileged) + ret = 2; + else + ret = 0; + if (Q_strncasecmp(s, "status", 6) == 0) + ret = 1; + else if (Q_strncasecmp(s, "god", 3) == 0) + ret = 1; + else if (Q_strncasecmp(s, "notarget", 8) == 0) + ret = 1; + else if (Q_strncasecmp(s, "fly", 3) == 0) + ret = 1; + else if (Q_strncasecmp(s, "name", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "noclip", 6) == 0) + ret = 1; + else if (Q_strncasecmp(s, "say", 3) == 0) + ret = 1; + else if (Q_strncasecmp(s, "say_team", 8) == 0) + ret = 1; + else if (Q_strncasecmp(s, "tell", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "color", 5) == 0) + ret = 1; + else if (Q_strncasecmp(s, "kill", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "pause", 5) == 0) + ret = 1; + else if (Q_strncasecmp(s, "spawn", 5) == 0) + ret = 1; + else if (Q_strncasecmp(s, "begin", 5) == 0) + ret = 1; + else if (Q_strncasecmp(s, "prespawn", 8) == 0) + ret = 1; + else if (Q_strncasecmp(s, "kick", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "ping", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "give", 4) == 0) + ret = 1; + else if (Q_strncasecmp(s, "ban", 3) == 0) + ret = 1; + if (ret == 2) + Cbuf_InsertText (s); + else if (ret == 1) + Cmd_ExecuteString (s, src_client); + else + Con_DPrintf("%s tried to %s\n", host_client->name, s); + break; + + case clc_disconnect: +// Sys_Printf ("SV_ReadClientMessage: client disconnected\n"); + return false; + + case clc_move: + SV_ReadClientMove (&host_client->cmd); + break; + } + } + } while (ret == 1); + + return true; +} + + +/* +================== +SV_RunClients +================== +*/ +void SV_RunClients (void) +{ + int i; + + for (i=0, host_client = svs.clients ; iactive) + continue; + + sv_player = host_client->edict; + + if (!SV_ReadClientMessage ()) + { + SV_DropClient (false); // client misbehaved... + continue; + } + + if (!host_client->spawned) + { + // clear client movement until a new packet is received + memset (&host_client->cmd, 0, sizeof(host_client->cmd)); + continue; + } + +// always pause in single player if in console or menus + if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) + SV_ClientThink (); + } +} + diff --git a/WinQuake/sys.h b/WinQuake/sys.h index c5d61a7..b3dddae 100644 --- a/WinQuake/sys.h +++ b/WinQuake/sys.h @@ -1,71 +1,71 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sys.h -- non-portable functions - -// -// file IO -// - -// returns the file size -// return -1 if file is not present -// the file should be in BINARY mode for stupid OSs that care -int Sys_FileOpenRead (char *path, int *hndl); - -int Sys_FileOpenWrite (char *path); -void Sys_FileClose (int handle); -void Sys_FileSeek (int handle, int position); -int Sys_FileRead (int handle, void *dest, int count); -int Sys_FileWrite (int handle, void *data, int count); -int Sys_FileTime (char *path); -void Sys_mkdir (char *path); - -// -// memory protection -// -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length); - -// -// system IO -// -void Sys_DebugLog(char *file, char *fmt, ...); - -void Sys_Error (char *error, ...); -// an error will cause the entire program to exit - -void Sys_Printf (char *fmt, ...); -// send text to the console - -void Sys_Quit (void); - -double Sys_FloatTime (void); - -char *Sys_ConsoleInput (void); - -void Sys_Sleep (void); -// called to yield for a little bit so as -// not to hog cpu when paused or debugging - -void Sys_SendKeyEvents (void); -// Perform Key_Event () callbacks until the input que is empty - -void Sys_LowFPPrecision (void); -void Sys_HighFPPrecision (void); -void Sys_SetFPCW (void); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sys.h -- non-portable functions + +// +// file IO +// + +// returns the file size +// return -1 if file is not present +// the file should be in BINARY mode for stupid OSs that care +int Sys_FileOpenRead (char *path, int *hndl); + +int Sys_FileOpenWrite (char *path); +void Sys_FileClose (int handle); +void Sys_FileSeek (int handle, int position); +int Sys_FileRead (int handle, void *dest, int count); +int Sys_FileWrite (int handle, void *data, int count); +int Sys_FileTime (char *path); +void Sys_mkdir (char *path); + +// +// memory protection +// +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length); + +// +// system IO +// +void Sys_DebugLog(char *file, char *fmt, ...); + +void Sys_Error (char *error, ...); +// an error will cause the entire program to exit + +void Sys_Printf (char *fmt, ...); +// send text to the console + +void Sys_Quit (void); + +double Sys_FloatTime (void); + +char *Sys_ConsoleInput (void); + +void Sys_Sleep (void); +// called to yield for a little bit so as +// not to hog cpu when paused or debugging + +void Sys_SendKeyEvents (void); +// Perform Key_Event () callbacks until the input que is empty + +void Sys_LowFPPrecision (void); +void Sys_HighFPPrecision (void); +void Sys_SetFPCW (void); + diff --git a/WinQuake/sys_dos.c b/WinQuake/sys_dos.c index 0a9bc4a..53afd78 100644 --- a/WinQuake/sys_dos.c +++ b/WinQuake/sys_dos.c @@ -1,953 +1,953 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "quakedef.h" -#include "dosisms.h" - -#define MINIMUM_WIN_MEMORY 0x800000 -#define MINIMUM_WIN_MEMORY_LEVELPAK (MINIMUM_WIN_MEMORY + 0x100000) - -int end_of_memory; -qboolean lockmem, lockunlockmem, unlockmem; -static int win95; - -#define STDOUT 1 - -#define KEYBUF_SIZE 256 -static unsigned char keybuf[KEYBUF_SIZE]; -static int keybuf_head=0; -static int keybuf_tail=0; - -static quakeparms_t quakeparms; -int sys_checksum; -static double curtime = 0.0; -static double lastcurtime = 0.0; -static double oldtime = 0.0; - -static qboolean isDedicated; - -static int minmem; - -float fptest_temp; - -extern char start_of_memory __asm__("start"); - -//============================================================================= - -// this is totally dependent on cwsdpmi putting the stack right after tge -// global data - -// This does evil things in a Win95 DOS box!!! -#if 0 -extern byte end; -#define CHECKBYTE 0xed -void Sys_InitStackCheck (void) -{ - int i; - - for (i=0 ; i<128*1024 ; i++) - (&end)[i] = CHECKBYTE; -} - -void Sys_StackCheck (void) -{ - int i; - - for (i=0 ; i<128*1024 ; i++) - if ( (&end)[i] != CHECKBYTE ) - break; - - Con_Printf ("%i undisturbed stack bytes\n", i); - if (end != CHECKBYTE) - Sys_Error ("System stack overflow!"); -} -#endif - -//============================================================================= - -byte scantokey[128] = - { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0 , 27, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1 - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2 - 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*', - K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 - K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME, - K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 - K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, - K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 - }; - -byte shiftscantokey[128] = - { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0 , 27, '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0 - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', 13 , K_CTRL,'A', 'S', // 1 - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '"' , '~', K_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2 - 'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*', - K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 - K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME, - K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4 - K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, - K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 - }; - -void TrapKey(void) -{ -// static int ctrl=0; - keybuf[keybuf_head] = dos_inportb(0x60); - dos_outportb(0x20, 0x20); - /* - if (scantokey[keybuf[keybuf_head]&0x7f] == K_CTRL) - ctrl=keybuf[keybuf_head]&0x80; - if (ctrl && scantokey[keybuf[keybuf_head]&0x7f] == 'c') - Sys_Error("ctrl-c hit\n"); - */ - keybuf_head = (keybuf_head + 1) & (KEYBUF_SIZE-1); -} - -#define SC_UPARROW 0x48 -#define SC_DOWNARROW 0x50 -#define SC_LEFTARROW 0x4b -#define SC_RIGHTARROW 0x4d -#define SC_LEFTSHIFT 0x2a -#define SC_RIGHTSHIFT 0x36 -#define SC_RIGHTARROW 0x4d - -void MaskExceptions (void); -void Sys_InitFloatTime (void); -void Sys_PushFPCW_SetHigh (void); -void Sys_PopFPCW (void); - -#define LEAVE_FOR_CACHE (512*1024) //FIXME: tune -#define LOCKED_FOR_MALLOC (128*1024) //FIXME: tune - - -void Sys_DetectWin95 (void) -{ - __dpmi_regs r; - - r.x.ax = 0x160a; /* Get Windows Version */ - __dpmi_int(0x2f, &r); - - if(r.x.ax || r.h.bh < 4) /* Not windows or earlier than Win95 */ - { - win95 = 0; - lockmem = true; - lockunlockmem = false; - unlockmem = true; - } - else - { - win95 = 1; - lockunlockmem = COM_CheckParm ("-winlockunlock"); - - if (lockunlockmem) - lockmem = true; - else - lockmem = COM_CheckParm ("-winlock"); - - unlockmem = lockmem && !lockunlockmem; - } -} - - -void *dos_getmaxlockedmem(int *size) -{ - __dpmi_free_mem_info meminfo; - __dpmi_meminfo info; - int working_size; - void *working_memory; - int last_locked; - int extra, i, j, allocsize; - static char *msg = "Locking data..."; - int m, n; - byte *x; - -// first lock all the current executing image so the locked count will -// be accurate. It doesn't hurt to lock the memory multiple times - last_locked = __djgpp_selector_limit + 1; - info.size = last_locked - 4096; - info.address = __djgpp_base_address + 4096; - - if (lockmem) - { - if(__dpmi_lock_linear_region(&info)) - { - Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n", - info.address, info.size/1024); - } - } - - __dpmi_get_free_memory_information(&meminfo); - - if (!win95) /* Not windows or earlier than Win95 */ - { - working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096; - } - else - { - working_size = meminfo.largest_available_free_block_in_bytes - - LEAVE_FOR_CACHE; - } - - working_size &= ~0xffff; /* Round down to 64K */ - working_size += 0x10000; - - do - { - working_size -= 0x10000; /* Decrease 64K and try again */ - working_memory = sbrk(working_size); - } while (working_memory == (void *)-1); - - extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff); - - if (extra > 0) - { - sbrk(extra); - working_size += extra; - } - -// now grab the memory - info.address = last_locked + __djgpp_base_address; - - if (!win95) - { - info.size = __djgpp_selector_limit + 1 - last_locked; - - while (info.size > 0 && __dpmi_lock_linear_region(&info)) - { - info.size -= 0x1000; - working_size -= 0x1000; - sbrk(-0x1000); - } - } - else - { /* Win95 section */ - j = COM_CheckParm("-winmem"); - - if (standard_quake) - minmem = MINIMUM_WIN_MEMORY; - else - minmem = MINIMUM_WIN_MEMORY_LEVELPAK; - - if (j) - { - allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 + - LOCKED_FOR_MALLOC; - - if (allocsize < (minmem + LOCKED_FOR_MALLOC)) - allocsize = minmem + LOCKED_FOR_MALLOC; - } - else - { - allocsize = minmem + LOCKED_FOR_MALLOC; - } - - if (!lockmem) - { - // we won't lock, just sbrk the memory - info.size = allocsize; - goto UpdateSbrk; - } - - // lock the memory down - write (STDOUT, msg, strlen (msg)); - - for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ; - j -= 0x100000) - { - info.size = j; - - if (!__dpmi_lock_linear_region(&info)) - goto Locked; - - write (STDOUT, ".", 1); - } - - // finally, try with the absolute minimum amount - for (i=0 ; i<10 ; i++) - { - info.size = minmem + LOCKED_FOR_MALLOC; - - if (!__dpmi_lock_linear_region(&info)) - goto Locked; - } - - Sys_Error ("Can't lock memory; %d Mb lockable RAM required. " - "Try shrinking smartdrv.", info.size / 0x100000); - -Locked: - -UpdateSbrk: - - info.address += info.size; - info.address -= __djgpp_base_address + 4; // ending point, malloc align - working_size = info.address - (int)working_memory; - sbrk(info.address-(int)sbrk(0)); // negative adjustment - } - - - if (lockunlockmem) - { - __dpmi_unlock_linear_region (&info); - printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000); - } - else if (lockmem) - { - printf ("Locked %d Mb data\n", working_size / 0x100000); - } - else - { - printf ("Allocated %d Mb data\n", working_size / 0x100000); - } - -// touch all the memory to make sure it's there. The 16-page skip is to -// keep Win 95 from thinking we're trying to page ourselves in (we are -// doing that, of course, but there's no reason we shouldn't) - x = (byte *)working_memory; - - for (n=0 ; n<4 ; n++) - { - for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4) - { - sys_checksum += *(int *)&x[m]; - sys_checksum += *(int *)&x[m + 16 * 0x1000]; - } - } - -// give some of what we locked back for malloc before returning. Done -// by cheating and passing a negative value to sbrk - working_size -= LOCKED_FOR_MALLOC; - sbrk( -(LOCKED_FOR_MALLOC)); - *size = working_size; - return working_memory; -} - - -/* -============ -Sys_FileTime - -returns -1 if not present -============ -*/ -int Sys_FileTime (char *path) -{ - struct stat buf; - - if (stat (path,&buf) == -1) - return -1; - - return buf.st_mtime; -} - -void Sys_mkdir (char *path) -{ - mkdir (path, 0777); -} - - -void Sys_Sleep(void) -{ -} - - -char *Sys_ConsoleInput(void) -{ - static char text[256]; - static int len = 0; - char ch; - - if (!isDedicated) - return NULL; - - if (! kbhit()) - return NULL; - - ch = getche(); - - switch (ch) - { - case '\r': - putch('\n'); - if (len) - { - text[len] = 0; - len = 0; - return text; - } - break; - - case '\b': - putch(' '); - if (len) - { - len--; - putch('\b'); - } - break; - - default: - text[len] = ch; - len = (len + 1) & 0xff; - break; - } - - return NULL; -} - -void Sys_Init(void) -{ - - MaskExceptions (); - - Sys_SetFPCW (); - - dos_outportb(0x43, 0x34); // set system timer to mode 2 - dos_outportb(0x40, 0); // for the Sys_FloatTime() function - dos_outportb(0x40, 0); - - Sys_InitFloatTime (); - - _go32_interrupt_stack_size = 4 * 1024;; - _go32_rmcb_stack_size = 4 * 1024; -} - -void Sys_Shutdown(void) -{ - if (!isDedicated) - dos_restoreintr(9); - - if (unlockmem) - { - dos_unlockmem (&start_of_memory, - end_of_memory - (int)&start_of_memory); - dos_unlockmem (quakeparms.membase, quakeparms.memsize); - } -} - - -#define SC_RSHIFT 0x36 -#define SC_LSHIFT 0x2a -void Sys_SendKeyEvents (void) -{ - int k, next; - int outkey; - -// get key events - - while (keybuf_head != keybuf_tail) - { - - k = keybuf[keybuf_tail++]; - keybuf_tail &= (KEYBUF_SIZE-1); - - if (k==0xe0) - continue; // special / pause keys - next = keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]; - if (next == 0xe1) - continue; // pause key bullshit - if (k==0xc5 && next == 0x9d) - { - Key_Event (K_PAUSE, true); - continue; - } - - // extended keyboard shift key bullshit - if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT ) - { - if ( keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]==0xe0 ) - continue; - k &= 0x80; - k |= SC_RSHIFT; - } - - if (k==0xc5 && keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)] == 0x9d) - continue; // more pause bullshit - - outkey = scantokey[k & 0x7f]; - - if (k & 0x80) - Key_Event (outkey, false); - else - Key_Event (outkey, true); - - } - -} - - -// ======================================================================= -// General routines -// ======================================================================= - -/* -================ -Sys_Printf -================ -*/ - -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - char text[1024]; - - va_start (argptr,fmt); - vsprintf (text,fmt,argptr); - va_end (argptr); - - if (cls.state == ca_dedicated) - fprintf(stderr, "%s", text); -} - -void Sys_AtExit (void) -{ - -// shutdown only once (so Sys_Error can call this function to shutdown, then -// print the error message, then call exit without exit calling this function -// again) - Sys_Shutdown(); -} - - -void Sys_Quit (void) -{ - byte screen[80*25*2]; - byte *d; - char ver[6]; - int i; - - -// load the sell screen before shuting everything down - if (registered.value) - d = COM_LoadHunkFile ("end2.bin"); - else - d = COM_LoadHunkFile ("end1.bin"); - if (d) - memcpy (screen, d, sizeof(screen)); - -// write the version number directly to the end screen - sprintf (ver, " v%4.2f", VERSION); - for (i=0 ; i<6 ; i++) - screen[0*80*2 + 72*2 + i*2] = ver[i]; - - Host_Shutdown(); - -// do the text mode sell screen - if (d) - { - memcpy ((void *)real2ptr(0xb8000), screen,80*25*2); - - // set text pos - regs.x.ax = 0x0200; - regs.h.bh = 0; - regs.h.dl = 0; - regs.h.dh = 22; - dos_int86 (0x10); - } - else - printf ("couldn't load endscreen.\n"); - - exit(0); -} - -void Sys_Error (char *error, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr,error); - vsprintf (string,error,argptr); - va_end (argptr); - - Host_Shutdown(); - fprintf(stderr, "Error: %s\n", string); -// Sys_AtExit is called by exit to shutdown the system - exit(0); -} - - -int Sys_FileOpenRead (char *path, int *handle) -{ - int h; - struct stat fileinfo; - - h = open (path, O_RDONLY|O_BINARY, 0666); - *handle = h; - if (h == -1) - return -1; - - if (fstat (h,&fileinfo) == -1) - Sys_Error ("Error fstating %s", path); - - return fileinfo.st_size; -} - -int Sys_FileOpenWrite (char *path) -{ - int handle; - - umask (0); - - handle = open(path,O_RDWR | O_BINARY | O_CREAT | O_TRUNC - , 0666); - - if (handle == -1) - Sys_Error ("Error opening %s: %s", path,strerror(errno)); - - return handle; -} - -void Sys_FileClose (int handle) -{ - close (handle); -} - -void Sys_FileSeek (int handle, int position) -{ - lseek (handle, position, SEEK_SET); -} - -int Sys_FileRead (int handle, void *dest, int count) -{ - return read (handle, dest, count); -} - -int Sys_FileWrite (int handle, void *data, int count) -{ - return write (handle, data, count); -} - -/* -================ -Sys_MakeCodeWriteable -================ -*/ -void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) -{ - // it's always writeable -} - - -/* -================ -Sys_FloatTime -================ -*/ -double Sys_FloatTime (void) -{ - int r; - unsigned t, tick; - double ft, time; - static int sametimecount; - - Sys_PushFPCW_SetHigh (); - -//{static float t = 0; t=t+0.05; return t;} // DEBUG - - t = *(unsigned short*)real2ptr(0x46c) * 65536; - - dos_outportb(0x43, 0); // latch time - r = dos_inportb(0x40); - r |= dos_inportb(0x40) << 8; - r = (r-1) & 0xffff; - - tick = *(unsigned short*)real2ptr(0x46c) * 65536; - if ((tick != t) && (r & 0x8000)) - t = tick; - - ft = (double) (t+(65536-r)) / 1193200.0; - time = ft - oldtime; - oldtime = ft; - - if (time < 0) - { - if (time > -3000.0) - time = 0.0; - else - time += 3600.0; - } - - curtime += time; - - if (curtime == lastcurtime) - { - sametimecount++; - - if (sametimecount > 100000) - { - curtime += 1.0; - sametimecount = 0; - } - } - else - { - sametimecount = 0; - } - - lastcurtime = curtime; - - Sys_PopFPCW (); - - return curtime; -} - - -/* -================ -Sys_InitFloatTime -================ -*/ -void Sys_InitFloatTime (void) -{ - int j; - - Sys_FloatTime (); - - oldtime = curtime; - - j = COM_CheckParm("-starttime"); - - if (j) - { - curtime = (double) (Q_atof(com_argv[j+1])); - } - else - { - curtime = 0.0; - } - lastcurtime = curtime; -} - - -/* -================ -Sys_GetMemory -================ -*/ -void Sys_GetMemory(void) -{ - int j, tsize; - - j = COM_CheckParm("-mem"); - if (j) - { - quakeparms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024); - quakeparms.membase = malloc (quakeparms.memsize); - } - else - { - quakeparms.membase = dos_getmaxlockedmem (&quakeparms.memsize); - } - - fprintf(stderr, "malloc'd: %d\n", quakeparms.memsize); - - if (COM_CheckParm ("-heapsize")) - { - tsize = Q_atoi (com_argv[COM_CheckParm("-heapsize") + 1]) * 1024; - - if (tsize < quakeparms.memsize) - quakeparms.memsize = tsize; - } -} - - -/* -================ -Sys_PageInProgram - -walks the text, data, and bss to make sure it's all paged in so that the -actual physical memory detected by Sys_GetMemory is correct. -================ -*/ -void Sys_PageInProgram(void) -{ - int i, j; - - end_of_memory = (int)sbrk(0); - - if (lockmem) - { - if (dos_lockmem ((void *)&start_of_memory, - end_of_memory - (int)&start_of_memory)) - Sys_Error ("Couldn't lock text and data"); - } - - if (lockunlockmem) - { - dos_unlockmem((void *)&start_of_memory, - end_of_memory - (int)&start_of_memory); - printf ("Locked and unlocked %d Mb image\n", - (end_of_memory - (int)&start_of_memory) / 0x100000); - } - else if (lockmem) - { - printf ("Locked %d Mb image\n", - (end_of_memory - (int)&start_of_memory) / 0x100000); - } - else - { - printf ("Loaded %d Mb image\n", - (end_of_memory - (int)&start_of_memory) / 0x100000); - } - -// touch the entire image, doing the 16-page skip so Win95 doesn't think we're -// trying to page ourselves in - for (j=0 ; j<4 ; j++) - { - for(i=(int)&start_of_memory ; i<(end_of_memory - 16 * 0x1000) ; i += 4) - { - sys_checksum += *(int *)i; - sys_checksum += *(int *)(i + 16 * 0x1000); - } - } -} - - -/* -================ -Sys_NoFPUExceptionHandler -================ -*/ -void Sys_NoFPUExceptionHandler(int whatever) -{ - printf ("\nError: Quake requires a floating-point processor\n"); - exit (0); -} - - -/* -================ -Sys_DefaultExceptionHandler -================ -*/ -void Sys_DefaultExceptionHandler(int whatever) -{ -} - - -/* -================ -main -================ -*/ -int main (int c, char **v) -{ - double time, oldtime, newtime; - extern void (*dos_error_func)(char *, ...); - static char cwd[1024]; - - printf ("Quake v%4.2f\n", VERSION); - -// make sure there's an FPU - signal(SIGNOFP, Sys_NoFPUExceptionHandler); - signal(SIGABRT, Sys_DefaultExceptionHandler); - signal(SIGALRM, Sys_DefaultExceptionHandler); - signal(SIGKILL, Sys_DefaultExceptionHandler); - signal(SIGQUIT, Sys_DefaultExceptionHandler); - signal(SIGINT, Sys_DefaultExceptionHandler); - - if (fptest_temp >= 0.0) - fptest_temp += 0.1; - - COM_InitArgv (c, v); - - quakeparms.argc = com_argc; - quakeparms.argv = com_argv; - - dos_error_func = Sys_Error; - - Sys_DetectWin95 (); - Sys_PageInProgram (); - Sys_GetMemory (); - - atexit (Sys_AtExit); // in case we crash - - getwd (cwd); - if (cwd[Q_strlen(cwd)-1] == '/') cwd[Q_strlen(cwd)-1] = 0; - quakeparms.basedir = cwd; //"f:/quake"; - - isDedicated = (COM_CheckParm ("-dedicated") != 0); - - Sys_Init (); - - if (!isDedicated) - dos_registerintr(9, TrapKey); - -//Sys_InitStackCheck (); - - Host_Init(&quakeparms); - -//Sys_StackCheck (); - -//Con_Printf ("Top of stack: 0x%x\n", &time); - oldtime = Sys_FloatTime (); - while (1) - { - newtime = Sys_FloatTime (); - time = newtime - oldtime; - - if (cls.state == ca_dedicated && (time +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "quakedef.h" +#include "dosisms.h" + +#define MINIMUM_WIN_MEMORY 0x800000 +#define MINIMUM_WIN_MEMORY_LEVELPAK (MINIMUM_WIN_MEMORY + 0x100000) + +int end_of_memory; +qboolean lockmem, lockunlockmem, unlockmem; +static int win95; + +#define STDOUT 1 + +#define KEYBUF_SIZE 256 +static unsigned char keybuf[KEYBUF_SIZE]; +static int keybuf_head=0; +static int keybuf_tail=0; + +static quakeparms_t quakeparms; +int sys_checksum; +static double curtime = 0.0; +static double lastcurtime = 0.0; +static double oldtime = 0.0; + +static qboolean isDedicated; + +static int minmem; + +float fptest_temp; + +extern char start_of_memory __asm__("start"); + +//============================================================================= + +// this is totally dependent on cwsdpmi putting the stack right after tge +// global data + +// This does evil things in a Win95 DOS box!!! +#if 0 +extern byte end; +#define CHECKBYTE 0xed +void Sys_InitStackCheck (void) +{ + int i; + + for (i=0 ; i<128*1024 ; i++) + (&end)[i] = CHECKBYTE; +} + +void Sys_StackCheck (void) +{ + int i; + + for (i=0 ; i<128*1024 ; i++) + if ( (&end)[i] != CHECKBYTE ) + break; + + Con_Printf ("%i undisturbed stack bytes\n", i); + if (end != CHECKBYTE) + Sys_Error ("System stack overflow!"); +} +#endif + +//============================================================================= + +byte scantokey[128] = + { +// 0 1 2 3 4 5 6 7 +// 8 9 A B C D E F + 0 , 27, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1 + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2 + 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*', + K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME, + K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 + K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, + K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 + }; + +byte shiftscantokey[128] = + { +// 0 1 2 3 4 5 6 7 +// 8 9 A B C D E F + 0 , 27, '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0 + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', 13 , K_CTRL,'A', 'S', // 1 + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '"' , '~', K_SHIFT,'|', 'Z', 'X', 'C', 'V', // 2 + 'B', 'N', 'M', '<', '>', '?', K_SHIFT,'*', + K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10,0 , 0 , K_HOME, + K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4 + K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, + K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 + }; + +void TrapKey(void) +{ +// static int ctrl=0; + keybuf[keybuf_head] = dos_inportb(0x60); + dos_outportb(0x20, 0x20); + /* + if (scantokey[keybuf[keybuf_head]&0x7f] == K_CTRL) + ctrl=keybuf[keybuf_head]&0x80; + if (ctrl && scantokey[keybuf[keybuf_head]&0x7f] == 'c') + Sys_Error("ctrl-c hit\n"); + */ + keybuf_head = (keybuf_head + 1) & (KEYBUF_SIZE-1); +} + +#define SC_UPARROW 0x48 +#define SC_DOWNARROW 0x50 +#define SC_LEFTARROW 0x4b +#define SC_RIGHTARROW 0x4d +#define SC_LEFTSHIFT 0x2a +#define SC_RIGHTSHIFT 0x36 +#define SC_RIGHTARROW 0x4d + +void MaskExceptions (void); +void Sys_InitFloatTime (void); +void Sys_PushFPCW_SetHigh (void); +void Sys_PopFPCW (void); + +#define LEAVE_FOR_CACHE (512*1024) //FIXME: tune +#define LOCKED_FOR_MALLOC (128*1024) //FIXME: tune + + +void Sys_DetectWin95 (void) +{ + __dpmi_regs r; + + r.x.ax = 0x160a; /* Get Windows Version */ + __dpmi_int(0x2f, &r); + + if(r.x.ax || r.h.bh < 4) /* Not windows or earlier than Win95 */ + { + win95 = 0; + lockmem = true; + lockunlockmem = false; + unlockmem = true; + } + else + { + win95 = 1; + lockunlockmem = COM_CheckParm ("-winlockunlock"); + + if (lockunlockmem) + lockmem = true; + else + lockmem = COM_CheckParm ("-winlock"); + + unlockmem = lockmem && !lockunlockmem; + } +} + + +void *dos_getmaxlockedmem(int *size) +{ + __dpmi_free_mem_info meminfo; + __dpmi_meminfo info; + int working_size; + void *working_memory; + int last_locked; + int extra, i, j, allocsize; + static char *msg = "Locking data..."; + int m, n; + byte *x; + +// first lock all the current executing image so the locked count will +// be accurate. It doesn't hurt to lock the memory multiple times + last_locked = __djgpp_selector_limit + 1; + info.size = last_locked - 4096; + info.address = __djgpp_base_address + 4096; + + if (lockmem) + { + if(__dpmi_lock_linear_region(&info)) + { + Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n", + info.address, info.size/1024); + } + } + + __dpmi_get_free_memory_information(&meminfo); + + if (!win95) /* Not windows or earlier than Win95 */ + { + working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096; + } + else + { + working_size = meminfo.largest_available_free_block_in_bytes - + LEAVE_FOR_CACHE; + } + + working_size &= ~0xffff; /* Round down to 64K */ + working_size += 0x10000; + + do + { + working_size -= 0x10000; /* Decrease 64K and try again */ + working_memory = sbrk(working_size); + } while (working_memory == (void *)-1); + + extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff); + + if (extra > 0) + { + sbrk(extra); + working_size += extra; + } + +// now grab the memory + info.address = last_locked + __djgpp_base_address; + + if (!win95) + { + info.size = __djgpp_selector_limit + 1 - last_locked; + + while (info.size > 0 && __dpmi_lock_linear_region(&info)) + { + info.size -= 0x1000; + working_size -= 0x1000; + sbrk(-0x1000); + } + } + else + { /* Win95 section */ + j = COM_CheckParm("-winmem"); + + if (standard_quake) + minmem = MINIMUM_WIN_MEMORY; + else + minmem = MINIMUM_WIN_MEMORY_LEVELPAK; + + if (j) + { + allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 + + LOCKED_FOR_MALLOC; + + if (allocsize < (minmem + LOCKED_FOR_MALLOC)) + allocsize = minmem + LOCKED_FOR_MALLOC; + } + else + { + allocsize = minmem + LOCKED_FOR_MALLOC; + } + + if (!lockmem) + { + // we won't lock, just sbrk the memory + info.size = allocsize; + goto UpdateSbrk; + } + + // lock the memory down + write (STDOUT, msg, strlen (msg)); + + for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ; + j -= 0x100000) + { + info.size = j; + + if (!__dpmi_lock_linear_region(&info)) + goto Locked; + + write (STDOUT, ".", 1); + } + + // finally, try with the absolute minimum amount + for (i=0 ; i<10 ; i++) + { + info.size = minmem + LOCKED_FOR_MALLOC; + + if (!__dpmi_lock_linear_region(&info)) + goto Locked; + } + + Sys_Error ("Can't lock memory; %d Mb lockable RAM required. " + "Try shrinking smartdrv.", info.size / 0x100000); + +Locked: + +UpdateSbrk: + + info.address += info.size; + info.address -= __djgpp_base_address + 4; // ending point, malloc align + working_size = info.address - (int)working_memory; + sbrk(info.address-(int)sbrk(0)); // negative adjustment + } + + + if (lockunlockmem) + { + __dpmi_unlock_linear_region (&info); + printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000); + } + else if (lockmem) + { + printf ("Locked %d Mb data\n", working_size / 0x100000); + } + else + { + printf ("Allocated %d Mb data\n", working_size / 0x100000); + } + +// touch all the memory to make sure it's there. The 16-page skip is to +// keep Win 95 from thinking we're trying to page ourselves in (we are +// doing that, of course, but there's no reason we shouldn't) + x = (byte *)working_memory; + + for (n=0 ; n<4 ; n++) + { + for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4) + { + sys_checksum += *(int *)&x[m]; + sys_checksum += *(int *)&x[m + 16 * 0x1000]; + } + } + +// give some of what we locked back for malloc before returning. Done +// by cheating and passing a negative value to sbrk + working_size -= LOCKED_FOR_MALLOC; + sbrk( -(LOCKED_FOR_MALLOC)); + *size = working_size; + return working_memory; +} + + +/* +============ +Sys_FileTime + +returns -1 if not present +============ +*/ +int Sys_FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + +void Sys_mkdir (char *path) +{ + mkdir (path, 0777); +} + + +void Sys_Sleep(void) +{ +} + + +char *Sys_ConsoleInput(void) +{ + static char text[256]; + static int len = 0; + char ch; + + if (!isDedicated) + return NULL; + + if (! kbhit()) + return NULL; + + ch = getche(); + + switch (ch) + { + case '\r': + putch('\n'); + if (len) + { + text[len] = 0; + len = 0; + return text; + } + break; + + case '\b': + putch(' '); + if (len) + { + len--; + putch('\b'); + } + break; + + default: + text[len] = ch; + len = (len + 1) & 0xff; + break; + } + + return NULL; +} + +void Sys_Init(void) +{ + + MaskExceptions (); + + Sys_SetFPCW (); + + dos_outportb(0x43, 0x34); // set system timer to mode 2 + dos_outportb(0x40, 0); // for the Sys_FloatTime() function + dos_outportb(0x40, 0); + + Sys_InitFloatTime (); + + _go32_interrupt_stack_size = 4 * 1024;; + _go32_rmcb_stack_size = 4 * 1024; +} + +void Sys_Shutdown(void) +{ + if (!isDedicated) + dos_restoreintr(9); + + if (unlockmem) + { + dos_unlockmem (&start_of_memory, + end_of_memory - (int)&start_of_memory); + dos_unlockmem (quakeparms.membase, quakeparms.memsize); + } +} + + +#define SC_RSHIFT 0x36 +#define SC_LSHIFT 0x2a +void Sys_SendKeyEvents (void) +{ + int k, next; + int outkey; + +// get key events + + while (keybuf_head != keybuf_tail) + { + + k = keybuf[keybuf_tail++]; + keybuf_tail &= (KEYBUF_SIZE-1); + + if (k==0xe0) + continue; // special / pause keys + next = keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]; + if (next == 0xe1) + continue; // pause key bullshit + if (k==0xc5 && next == 0x9d) + { + Key_Event (K_PAUSE, true); + continue; + } + + // extended keyboard shift key bullshit + if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT ) + { + if ( keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]==0xe0 ) + continue; + k &= 0x80; + k |= SC_RSHIFT; + } + + if (k==0xc5 && keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)] == 0x9d) + continue; // more pause bullshit + + outkey = scantokey[k & 0x7f]; + + if (k & 0x80) + Key_Event (outkey, false); + else + Key_Event (outkey, true); + + } + +} + + +// ======================================================================= +// General routines +// ======================================================================= + +/* +================ +Sys_Printf +================ +*/ + +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[1024]; + + va_start (argptr,fmt); + vsprintf (text,fmt,argptr); + va_end (argptr); + + if (cls.state == ca_dedicated) + fprintf(stderr, "%s", text); +} + +void Sys_AtExit (void) +{ + +// shutdown only once (so Sys_Error can call this function to shutdown, then +// print the error message, then call exit without exit calling this function +// again) + Sys_Shutdown(); +} + + +void Sys_Quit (void) +{ + byte screen[80*25*2]; + byte *d; + char ver[6]; + int i; + + +// load the sell screen before shuting everything down + if (registered.value) + d = COM_LoadHunkFile ("end2.bin"); + else + d = COM_LoadHunkFile ("end1.bin"); + if (d) + memcpy (screen, d, sizeof(screen)); + +// write the version number directly to the end screen + sprintf (ver, " v%4.2f", VERSION); + for (i=0 ; i<6 ; i++) + screen[0*80*2 + 72*2 + i*2] = ver[i]; + + Host_Shutdown(); + +// do the text mode sell screen + if (d) + { + memcpy ((void *)real2ptr(0xb8000), screen,80*25*2); + + // set text pos + regs.x.ax = 0x0200; + regs.h.bh = 0; + regs.h.dl = 0; + regs.h.dh = 22; + dos_int86 (0x10); + } + else + printf ("couldn't load endscreen.\n"); + + exit(0); +} + +void Sys_Error (char *error, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + + Host_Shutdown(); + fprintf(stderr, "Error: %s\n", string); +// Sys_AtExit is called by exit to shutdown the system + exit(0); +} + + +int Sys_FileOpenRead (char *path, int *handle) +{ + int h; + struct stat fileinfo; + + h = open (path, O_RDONLY|O_BINARY, 0666); + *handle = h; + if (h == -1) + return -1; + + if (fstat (h,&fileinfo) == -1) + Sys_Error ("Error fstating %s", path); + + return fileinfo.st_size; +} + +int Sys_FileOpenWrite (char *path) +{ + int handle; + + umask (0); + + handle = open(path,O_RDWR | O_BINARY | O_CREAT | O_TRUNC + , 0666); + + if (handle == -1) + Sys_Error ("Error opening %s: %s", path,strerror(errno)); + + return handle; +} + +void Sys_FileClose (int handle) +{ + close (handle); +} + +void Sys_FileSeek (int handle, int position) +{ + lseek (handle, position, SEEK_SET); +} + +int Sys_FileRead (int handle, void *dest, int count) +{ + return read (handle, dest, count); +} + +int Sys_FileWrite (int handle, void *data, int count) +{ + return write (handle, data, count); +} + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + // it's always writeable +} + + +/* +================ +Sys_FloatTime +================ +*/ +double Sys_FloatTime (void) +{ + int r; + unsigned t, tick; + double ft, time; + static int sametimecount; + + Sys_PushFPCW_SetHigh (); + +//{static float t = 0; t=t+0.05; return t;} // DEBUG + + t = *(unsigned short*)real2ptr(0x46c) * 65536; + + dos_outportb(0x43, 0); // latch time + r = dos_inportb(0x40); + r |= dos_inportb(0x40) << 8; + r = (r-1) & 0xffff; + + tick = *(unsigned short*)real2ptr(0x46c) * 65536; + if ((tick != t) && (r & 0x8000)) + t = tick; + + ft = (double) (t+(65536-r)) / 1193200.0; + time = ft - oldtime; + oldtime = ft; + + if (time < 0) + { + if (time > -3000.0) + time = 0.0; + else + time += 3600.0; + } + + curtime += time; + + if (curtime == lastcurtime) + { + sametimecount++; + + if (sametimecount > 100000) + { + curtime += 1.0; + sametimecount = 0; + } + } + else + { + sametimecount = 0; + } + + lastcurtime = curtime; + + Sys_PopFPCW (); + + return curtime; +} + + +/* +================ +Sys_InitFloatTime +================ +*/ +void Sys_InitFloatTime (void) +{ + int j; + + Sys_FloatTime (); + + oldtime = curtime; + + j = COM_CheckParm("-starttime"); + + if (j) + { + curtime = (double) (Q_atof(com_argv[j+1])); + } + else + { + curtime = 0.0; + } + lastcurtime = curtime; +} + + +/* +================ +Sys_GetMemory +================ +*/ +void Sys_GetMemory(void) +{ + int j, tsize; + + j = COM_CheckParm("-mem"); + if (j) + { + quakeparms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024); + quakeparms.membase = malloc (quakeparms.memsize); + } + else + { + quakeparms.membase = dos_getmaxlockedmem (&quakeparms.memsize); + } + + fprintf(stderr, "malloc'd: %d\n", quakeparms.memsize); + + if (COM_CheckParm ("-heapsize")) + { + tsize = Q_atoi (com_argv[COM_CheckParm("-heapsize") + 1]) * 1024; + + if (tsize < quakeparms.memsize) + quakeparms.memsize = tsize; + } +} + + +/* +================ +Sys_PageInProgram + +walks the text, data, and bss to make sure it's all paged in so that the +actual physical memory detected by Sys_GetMemory is correct. +================ +*/ +void Sys_PageInProgram(void) +{ + int i, j; + + end_of_memory = (int)sbrk(0); + + if (lockmem) + { + if (dos_lockmem ((void *)&start_of_memory, + end_of_memory - (int)&start_of_memory)) + Sys_Error ("Couldn't lock text and data"); + } + + if (lockunlockmem) + { + dos_unlockmem((void *)&start_of_memory, + end_of_memory - (int)&start_of_memory); + printf ("Locked and unlocked %d Mb image\n", + (end_of_memory - (int)&start_of_memory) / 0x100000); + } + else if (lockmem) + { + printf ("Locked %d Mb image\n", + (end_of_memory - (int)&start_of_memory) / 0x100000); + } + else + { + printf ("Loaded %d Mb image\n", + (end_of_memory - (int)&start_of_memory) / 0x100000); + } + +// touch the entire image, doing the 16-page skip so Win95 doesn't think we're +// trying to page ourselves in + for (j=0 ; j<4 ; j++) + { + for(i=(int)&start_of_memory ; i<(end_of_memory - 16 * 0x1000) ; i += 4) + { + sys_checksum += *(int *)i; + sys_checksum += *(int *)(i + 16 * 0x1000); + } + } +} + + +/* +================ +Sys_NoFPUExceptionHandler +================ +*/ +void Sys_NoFPUExceptionHandler(int whatever) +{ + printf ("\nError: Quake requires a floating-point processor\n"); + exit (0); +} + + +/* +================ +Sys_DefaultExceptionHandler +================ +*/ +void Sys_DefaultExceptionHandler(int whatever) +{ +} + + +/* +================ +main +================ +*/ +int main (int c, char **v) +{ + double time, oldtime, newtime; + extern void (*dos_error_func)(char *, ...); + static char cwd[1024]; + + printf ("Quake v%4.2f\n", VERSION); + +// make sure there's an FPU + signal(SIGNOFP, Sys_NoFPUExceptionHandler); + signal(SIGABRT, Sys_DefaultExceptionHandler); + signal(SIGALRM, Sys_DefaultExceptionHandler); + signal(SIGKILL, Sys_DefaultExceptionHandler); + signal(SIGQUIT, Sys_DefaultExceptionHandler); + signal(SIGINT, Sys_DefaultExceptionHandler); + + if (fptest_temp >= 0.0) + fptest_temp += 0.1; + + COM_InitArgv (c, v); + + quakeparms.argc = com_argc; + quakeparms.argv = com_argv; + + dos_error_func = Sys_Error; + + Sys_DetectWin95 (); + Sys_PageInProgram (); + Sys_GetMemory (); + + atexit (Sys_AtExit); // in case we crash + + getwd (cwd); + if (cwd[Q_strlen(cwd)-1] == '/') cwd[Q_strlen(cwd)-1] = 0; + quakeparms.basedir = cwd; //"f:/quake"; + + isDedicated = (COM_CheckParm ("-dedicated") != 0); + + Sys_Init (); + + if (!isDedicated) + dos_registerintr(9, TrapKey); + +//Sys_InitStackCheck (); + + Host_Init(&quakeparms); + +//Sys_StackCheck (); + +//Con_Printf ("Top of stack: 0x%x\n", &time); + oldtime = Sys_FloatTime (); + while (1) + { + newtime = Sys_FloatTime (); + time = newtime - oldtime; + + if (cls.state == ca_dedicated && (time 2000000.0)) - { - lowshift++; - lowpart >>= 1; - lowpart |= (highpart & 1) << 31; - highpart >>= 1; - } - - pfreq = 1.0 / (double)lowpart; - - Sys_InitFloatTime (); - - vinfo.dwOSVersionInfoSize = sizeof(vinfo); - - if (!GetVersionEx (&vinfo)) - Sys_Error ("Couldn't get OS info"); - - if ((vinfo.dwMajorVersion < 4) || - (vinfo.dwPlatformId == VER_PLATFORM_WIN32s)) - { - Sys_Error ("WinQuake requires at least Win95 or NT 4.0"); - } - - if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) - WinNT = true; - else - WinNT = false; -} - - -void Sys_Error (char *error, ...) -{ - va_list argptr; - char text[1024], text2[1024]; - char *text3 = "Press Enter to exit\n"; - char *text4 = "***********************************\n"; - char *text5 = "\n"; - DWORD dummy; - double starttime; - static int in_sys_error0 = 0; - static int in_sys_error1 = 0; - static int in_sys_error2 = 0; - static int in_sys_error3 = 0; - - if (!in_sys_error3) - { - in_sys_error3 = 1; - VID_ForceUnlockedAndReturnState (); - } - - va_start (argptr, error); - vsprintf (text, error, argptr); - va_end (argptr); - - if (isDedicated) - { - va_start (argptr, error); - vsprintf (text, error, argptr); - va_end (argptr); - - sprintf (text2, "ERROR: %s\n", text); - WriteFile (houtput, text5, strlen (text5), &dummy, NULL); - WriteFile (houtput, text4, strlen (text4), &dummy, NULL); - WriteFile (houtput, text2, strlen (text2), &dummy, NULL); - WriteFile (houtput, text3, strlen (text3), &dummy, NULL); - WriteFile (houtput, text4, strlen (text4), &dummy, NULL); - - - starttime = Sys_FloatTime (); - sc_return_on_enter = true; // so Enter will get us out of here - - while (!Sys_ConsoleInput () && - ((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT)) - { - } - } - else - { - // switch to windowed so the message box is visible, unless we already - // tried that and failed - if (!in_sys_error0) - { - in_sys_error0 = 1; - VID_SetDefaultMode (); - MessageBox(NULL, text, "Quake Error", - MB_OK | MB_SETFOREGROUND | MB_ICONSTOP); - } - else - { - MessageBox(NULL, text, "Double Quake Error", - MB_OK | MB_SETFOREGROUND | MB_ICONSTOP); - } - } - - if (!in_sys_error1) - { - in_sys_error1 = 1; - Host_Shutdown (); - } - -// shut down QHOST hooks if necessary - if (!in_sys_error2) - { - in_sys_error2 = 1; - DeinitConProc (); - } - - exit (1); -} - -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - char text[1024]; - DWORD dummy; - - if (isDedicated) - { - va_start (argptr,fmt); - vsprintf (text, fmt, argptr); - va_end (argptr); - - WriteFile(houtput, text, strlen (text), &dummy, NULL); - } -} - -void Sys_Quit (void) -{ - - VID_ForceUnlockedAndReturnState (); - - Host_Shutdown(); - - if (tevent) - CloseHandle (tevent); - - if (isDedicated) - FreeConsole (); - -// shut down QHOST hooks if necessary - DeinitConProc (); - - exit (0); -} - - -/* -================ -Sys_FloatTime -================ -*/ -double Sys_FloatTime (void) -{ - static int sametimecount; - static unsigned int oldtime; - static int first = 1; - LARGE_INTEGER PerformanceCount; - unsigned int temp, t2; - double time; - - Sys_PushFPCW_SetHigh (); - - QueryPerformanceCounter (&PerformanceCount); - - temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) | - ((unsigned int)PerformanceCount.HighPart << (32 - lowshift)); - - if (first) - { - oldtime = temp; - first = 0; - } - else - { - // check for turnover or backward time - if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000)) - { - oldtime = temp; // so we can't get stuck - } - else - { - t2 = temp - oldtime; - - time = (double)t2 * pfreq; - oldtime = temp; - - curtime += time; - - if (curtime == lastcurtime) - { - sametimecount++; - - if (sametimecount > 100000) - { - curtime += 1.0; - sametimecount = 0; - } - } - else - { - sametimecount = 0; - } - - lastcurtime = curtime; - } - } - - Sys_PopFPCW (); - - return curtime; -} - - -/* -================ -Sys_InitFloatTime -================ -*/ -void Sys_InitFloatTime (void) -{ - int j; - - Sys_FloatTime (); - - j = COM_CheckParm("-starttime"); - - if (j) - { - curtime = (double) (Q_atof(com_argv[j+1])); - } - else - { - curtime = 0.0; - } - - lastcurtime = curtime; -} - - -char *Sys_ConsoleInput (void) -{ - static char text[256]; - static int len; - INPUT_RECORD recs[1024]; - int count; - int i, dummy; - int ch, numread, numevents; - - if (!isDedicated) - return NULL; - - - for ( ;; ) - { - if (!GetNumberOfConsoleInputEvents (hinput, &numevents)) - Sys_Error ("Error getting # of console events"); - - if (numevents <= 0) - break; - - if (!ReadConsoleInput(hinput, recs, 1, &numread)) - Sys_Error ("Error reading console input"); - - if (numread != 1) - Sys_Error ("Couldn't read console input"); - - if (recs[0].EventType == KEY_EVENT) - { - if (!recs[0].Event.KeyEvent.bKeyDown) - { - ch = recs[0].Event.KeyEvent.uChar.AsciiChar; - - switch (ch) - { - case '\r': - WriteFile(houtput, "\r\n", 2, &dummy, NULL); - - if (len) - { - text[len] = 0; - len = 0; - return text; - } - else if (sc_return_on_enter) - { - // special case to allow exiting from the error handler on Enter - text[0] = '\r'; - len = 0; - return text; - } - - break; - - case '\b': - WriteFile(houtput, "\b \b", 3, &dummy, NULL); - if (len) - { - len--; - } - break; - - default: - if (ch >= ' ') - { - WriteFile(houtput, &ch, 1, &dummy, NULL); - text[len] = ch; - len = (len + 1) & 0xff; - } - - break; - - } - } - } - } - - return NULL; -} - -void Sys_Sleep (void) -{ - Sleep (1); -} - - -void Sys_SendKeyEvents (void) -{ - MSG msg; - - while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) - { - // we always update if there are any event, even if we're paused - scr_skipupdate = 0; - - if (!GetMessage (&msg, NULL, 0, 0)) - Sys_Quit (); - - TranslateMessage (&msg); - DispatchMessage (&msg); - } -} - - -/* -============================================================================== - - WINDOWS CRAP - -============================================================================== -*/ - - -/* -================== -WinMain -================== -*/ -void SleepUntilInput (int time) -{ - - MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT); -} - - -/* -================== -WinMain -================== -*/ -HINSTANCE global_hInstance; -int global_nCmdShow; -char *argv[MAX_NUM_ARGVS]; -static char *empty_string = ""; -HWND hwnd_dialog; - - -int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -{ - MSG msg; - quakeparms_t parms; - double time, oldtime, newtime; - MEMORYSTATUS lpBuffer; - static char cwd[1024]; - int t; - RECT rect; - - /* previous instances do not exist in Win32 */ - if (hPrevInstance) - return 0; - - global_hInstance = hInstance; - global_nCmdShow = nCmdShow; - - lpBuffer.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus (&lpBuffer); - - if (!GetCurrentDirectory (sizeof(cwd), cwd)) - Sys_Error ("Couldn't determine current directory"); - - if (cwd[Q_strlen(cwd)-1] == '/') - cwd[Q_strlen(cwd)-1] = 0; - - parms.basedir = cwd; - parms.cachedir = NULL; - - parms.argc = 1; - argv[0] = empty_string; - - while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS)) - { - while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) - lpCmdLine++; - - if (*lpCmdLine) - { - argv[parms.argc] = lpCmdLine; - parms.argc++; - - while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) - lpCmdLine++; - - if (*lpCmdLine) - { - *lpCmdLine = 0; - lpCmdLine++; - } - - } - } - - parms.argv = argv; - - COM_InitArgv (parms.argc, parms.argv); - - parms.argc = com_argc; - parms.argv = com_argv; - - isDedicated = (COM_CheckParm ("-dedicated") != 0); - - if (!isDedicated) - { - hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL); - - if (hwnd_dialog) - { - if (GetWindowRect (hwnd_dialog, &rect)) - { - if (rect.left > (rect.top * 2)) - { - SetWindowPos (hwnd_dialog, 0, - (rect.left / 2) - ((rect.right - rect.left) / 2), - rect.top, 0, 0, - SWP_NOZORDER | SWP_NOSIZE); - } - } - - ShowWindow (hwnd_dialog, SW_SHOWDEFAULT); - UpdateWindow (hwnd_dialog); - SetForegroundWindow (hwnd_dialog); - } - } - -// take the greater of all the available memory or half the total memory, -// but at least 8 Mb and no more than 16 Mb, unless they explicitly -// request otherwise - parms.memsize = lpBuffer.dwAvailPhys; - - if (parms.memsize < MINIMUM_WIN_MEMORY) - parms.memsize = MINIMUM_WIN_MEMORY; - - if (parms.memsize < (lpBuffer.dwTotalPhys >> 1)) - parms.memsize = lpBuffer.dwTotalPhys >> 1; - - if (parms.memsize > MAXIMUM_WIN_MEMORY) - parms.memsize = MAXIMUM_WIN_MEMORY; - - if (COM_CheckParm ("-heapsize")) - { - t = COM_CheckParm("-heapsize") + 1; - - if (t < com_argc) - parms.memsize = Q_atoi (com_argv[t]) * 1024; - } - - parms.membase = malloc (parms.memsize); - - if (!parms.membase) - Sys_Error ("Not enough memory free; check disk space\n"); - - Sys_PageIn (parms.membase, parms.memsize); - - tevent = CreateEvent(NULL, FALSE, FALSE, NULL); - - if (!tevent) - Sys_Error ("Couldn't create event"); - - if (isDedicated) - { - if (!AllocConsole ()) - { - Sys_Error ("Couldn't create dedicated server console"); - } - - hinput = GetStdHandle (STD_INPUT_HANDLE); - houtput = GetStdHandle (STD_OUTPUT_HANDLE); - - // give QHOST a chance to hook into the console - if ((t = COM_CheckParm ("-HFILE")) > 0) - { - if (t < com_argc) - hFile = (HANDLE)Q_atoi (com_argv[t+1]); - } - - if ((t = COM_CheckParm ("-HPARENT")) > 0) - { - if (t < com_argc) - heventParent = (HANDLE)Q_atoi (com_argv[t+1]); - } - - if ((t = COM_CheckParm ("-HCHILD")) > 0) - { - if (t < com_argc) - heventChild = (HANDLE)Q_atoi (com_argv[t+1]); - } - - InitConProc (hFile, heventParent, heventChild); - } - - Sys_Init (); - -// because sound is off until we become active - S_BlockSound (); - - Sys_Printf ("Host_Init\n"); - Host_Init (&parms); - - oldtime = Sys_FloatTime (); - - /* main window message loop */ - while (1) - { - if (isDedicated) - { - newtime = Sys_FloatTime (); - time = newtime - oldtime; - - while (time < sys_ticrate.value ) - { - Sys_Sleep(); - newtime = Sys_FloatTime (); - time = newtime - oldtime; - } - } - else - { - // yield the CPU for a little while when paused, minimized, or not the focus - if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing) - { - SleepUntilInput (PAUSE_SLEEP); - scr_skipupdate = 1; // no point in bothering to draw - } - else if (!ActiveApp && !DDActive) - { - SleepUntilInput (NOT_FOCUS_SLEEP); - } - - newtime = Sys_FloatTime (); - time = newtime - oldtime; - } - - Host_Frame (time); - oldtime = newtime; - } - - /* return success of application */ - return TRUE; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sys_win.c -- Win32 system interface code + +#include "quakedef.h" +#include "winquake.h" +#include "errno.h" +#include "resource.h" +#include "conproc.h" + +#define MINIMUM_WIN_MEMORY 0x0880000 +#define MAXIMUM_WIN_MEMORY 0x1000000 + +#define CONSOLE_ERROR_TIMEOUT 60.0 // # of seconds to wait on Sys_Error running + // dedicated before exiting +#define PAUSE_SLEEP 50 // sleep time on pause or minimization +#define NOT_FOCUS_SLEEP 20 // sleep time when not focus + +int starttime; +qboolean ActiveApp, Minimized; +qboolean WinNT; + +static double pfreq; +static double curtime = 0.0; +static double lastcurtime = 0.0; +static int lowshift; +qboolean isDedicated; +static qboolean sc_return_on_enter = false; +HANDLE hinput, houtput; + +static char *tracking_tag = "Clams & Mooses"; + +static HANDLE tevent; +static HANDLE hFile; +static HANDLE heventParent; +static HANDLE heventChild; + +void MaskExceptions (void); +void Sys_InitFloatTime (void); +void Sys_PushFPCW_SetHigh (void); +void Sys_PopFPCW (void); + +volatile int sys_checksum; + + +/* +================ +Sys_PageIn +================ +*/ +void Sys_PageIn (void *ptr, int size) +{ + byte *x; + int j, m, n; + +// touch all the memory to make sure it's there. The 16-page skip is to +// keep Win 95 from thinking we're trying to page ourselves in (we are +// doing that, of course, but there's no reason we shouldn't) + x = (byte *)ptr; + + for (n=0 ; n<4 ; n++) + { + for (m=0 ; m<(size - 16 * 0x1000) ; m += 4) + { + sys_checksum += *(int *)&x[m]; + sys_checksum += *(int *)&x[m + 16 * 0x1000]; + } + } +} + + +/* +=============================================================================== + +FILE IO + +=============================================================================== +*/ + +#define MAX_HANDLES 10 +FILE *sys_handles[MAX_HANDLES]; + +int findhandle (void) +{ + int i; + + for (i=1 ; i 2000000.0)) + { + lowshift++; + lowpart >>= 1; + lowpart |= (highpart & 1) << 31; + highpart >>= 1; + } + + pfreq = 1.0 / (double)lowpart; + + Sys_InitFloatTime (); + + vinfo.dwOSVersionInfoSize = sizeof(vinfo); + + if (!GetVersionEx (&vinfo)) + Sys_Error ("Couldn't get OS info"); + + if ((vinfo.dwMajorVersion < 4) || + (vinfo.dwPlatformId == VER_PLATFORM_WIN32s)) + { + Sys_Error ("WinQuake requires at least Win95 or NT 4.0"); + } + + if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) + WinNT = true; + else + WinNT = false; +} + + +void Sys_Error (char *error, ...) +{ + va_list argptr; + char text[1024], text2[1024]; + char *text3 = "Press Enter to exit\n"; + char *text4 = "***********************************\n"; + char *text5 = "\n"; + DWORD dummy; + double starttime; + static int in_sys_error0 = 0; + static int in_sys_error1 = 0; + static int in_sys_error2 = 0; + static int in_sys_error3 = 0; + + if (!in_sys_error3) + { + in_sys_error3 = 1; + VID_ForceUnlockedAndReturnState (); + } + + va_start (argptr, error); + vsprintf (text, error, argptr); + va_end (argptr); + + if (isDedicated) + { + va_start (argptr, error); + vsprintf (text, error, argptr); + va_end (argptr); + + sprintf (text2, "ERROR: %s\n", text); + WriteFile (houtput, text5, strlen (text5), &dummy, NULL); + WriteFile (houtput, text4, strlen (text4), &dummy, NULL); + WriteFile (houtput, text2, strlen (text2), &dummy, NULL); + WriteFile (houtput, text3, strlen (text3), &dummy, NULL); + WriteFile (houtput, text4, strlen (text4), &dummy, NULL); + + + starttime = Sys_FloatTime (); + sc_return_on_enter = true; // so Enter will get us out of here + + while (!Sys_ConsoleInput () && + ((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT)) + { + } + } + else + { + // switch to windowed so the message box is visible, unless we already + // tried that and failed + if (!in_sys_error0) + { + in_sys_error0 = 1; + VID_SetDefaultMode (); + MessageBox(NULL, text, "Quake Error", + MB_OK | MB_SETFOREGROUND | MB_ICONSTOP); + } + else + { + MessageBox(NULL, text, "Double Quake Error", + MB_OK | MB_SETFOREGROUND | MB_ICONSTOP); + } + } + + if (!in_sys_error1) + { + in_sys_error1 = 1; + Host_Shutdown (); + } + +// shut down QHOST hooks if necessary + if (!in_sys_error2) + { + in_sys_error2 = 1; + DeinitConProc (); + } + + exit (1); +} + +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[1024]; + DWORD dummy; + + if (isDedicated) + { + va_start (argptr,fmt); + vsprintf (text, fmt, argptr); + va_end (argptr); + + WriteFile(houtput, text, strlen (text), &dummy, NULL); + } +} + +void Sys_Quit (void) +{ + + VID_ForceUnlockedAndReturnState (); + + Host_Shutdown(); + + if (tevent) + CloseHandle (tevent); + + if (isDedicated) + FreeConsole (); + +// shut down QHOST hooks if necessary + DeinitConProc (); + + exit (0); +} + + +/* +================ +Sys_FloatTime +================ +*/ +double Sys_FloatTime (void) +{ + static int sametimecount; + static unsigned int oldtime; + static int first = 1; + LARGE_INTEGER PerformanceCount; + unsigned int temp, t2; + double time; + + Sys_PushFPCW_SetHigh (); + + QueryPerformanceCounter (&PerformanceCount); + + temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) | + ((unsigned int)PerformanceCount.HighPart << (32 - lowshift)); + + if (first) + { + oldtime = temp; + first = 0; + } + else + { + // check for turnover or backward time + if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000)) + { + oldtime = temp; // so we can't get stuck + } + else + { + t2 = temp - oldtime; + + time = (double)t2 * pfreq; + oldtime = temp; + + curtime += time; + + if (curtime == lastcurtime) + { + sametimecount++; + + if (sametimecount > 100000) + { + curtime += 1.0; + sametimecount = 0; + } + } + else + { + sametimecount = 0; + } + + lastcurtime = curtime; + } + } + + Sys_PopFPCW (); + + return curtime; +} + + +/* +================ +Sys_InitFloatTime +================ +*/ +void Sys_InitFloatTime (void) +{ + int j; + + Sys_FloatTime (); + + j = COM_CheckParm("-starttime"); + + if (j) + { + curtime = (double) (Q_atof(com_argv[j+1])); + } + else + { + curtime = 0.0; + } + + lastcurtime = curtime; +} + + +char *Sys_ConsoleInput (void) +{ + static char text[256]; + static int len; + INPUT_RECORD recs[1024]; + int count; + int i, dummy; + int ch, numread, numevents; + + if (!isDedicated) + return NULL; + + + for ( ;; ) + { + if (!GetNumberOfConsoleInputEvents (hinput, &numevents)) + Sys_Error ("Error getting # of console events"); + + if (numevents <= 0) + break; + + if (!ReadConsoleInput(hinput, recs, 1, &numread)) + Sys_Error ("Error reading console input"); + + if (numread != 1) + Sys_Error ("Couldn't read console input"); + + if (recs[0].EventType == KEY_EVENT) + { + if (!recs[0].Event.KeyEvent.bKeyDown) + { + ch = recs[0].Event.KeyEvent.uChar.AsciiChar; + + switch (ch) + { + case '\r': + WriteFile(houtput, "\r\n", 2, &dummy, NULL); + + if (len) + { + text[len] = 0; + len = 0; + return text; + } + else if (sc_return_on_enter) + { + // special case to allow exiting from the error handler on Enter + text[0] = '\r'; + len = 0; + return text; + } + + break; + + case '\b': + WriteFile(houtput, "\b \b", 3, &dummy, NULL); + if (len) + { + len--; + } + break; + + default: + if (ch >= ' ') + { + WriteFile(houtput, &ch, 1, &dummy, NULL); + text[len] = ch; + len = (len + 1) & 0xff; + } + + break; + + } + } + } + } + + return NULL; +} + +void Sys_Sleep (void) +{ + Sleep (1); +} + + +void Sys_SendKeyEvents (void) +{ + MSG msg; + + while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + // we always update if there are any event, even if we're paused + scr_skipupdate = 0; + + if (!GetMessage (&msg, NULL, 0, 0)) + Sys_Quit (); + + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + + +/* +============================================================================== + + WINDOWS CRAP + +============================================================================== +*/ + + +/* +================== +WinMain +================== +*/ +void SleepUntilInput (int time) +{ + + MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT); +} + + +/* +================== +WinMain +================== +*/ +HINSTANCE global_hInstance; +int global_nCmdShow; +char *argv[MAX_NUM_ARGVS]; +static char *empty_string = ""; +HWND hwnd_dialog; + + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + quakeparms_t parms; + double time, oldtime, newtime; + MEMORYSTATUS lpBuffer; + static char cwd[1024]; + int t; + RECT rect; + + /* previous instances do not exist in Win32 */ + if (hPrevInstance) + return 0; + + global_hInstance = hInstance; + global_nCmdShow = nCmdShow; + + lpBuffer.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus (&lpBuffer); + + if (!GetCurrentDirectory (sizeof(cwd), cwd)) + Sys_Error ("Couldn't determine current directory"); + + if (cwd[Q_strlen(cwd)-1] == '/') + cwd[Q_strlen(cwd)-1] = 0; + + parms.basedir = cwd; + parms.cachedir = NULL; + + parms.argc = 1; + argv[0] = empty_string; + + while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS)) + { + while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + argv[parms.argc] = lpCmdLine; + parms.argc++; + + while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) + lpCmdLine++; + + if (*lpCmdLine) + { + *lpCmdLine = 0; + lpCmdLine++; + } + + } + } + + parms.argv = argv; + + COM_InitArgv (parms.argc, parms.argv); + + parms.argc = com_argc; + parms.argv = com_argv; + + isDedicated = (COM_CheckParm ("-dedicated") != 0); + + if (!isDedicated) + { + hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL); + + if (hwnd_dialog) + { + if (GetWindowRect (hwnd_dialog, &rect)) + { + if (rect.left > (rect.top * 2)) + { + SetWindowPos (hwnd_dialog, 0, + (rect.left / 2) - ((rect.right - rect.left) / 2), + rect.top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE); + } + } + + ShowWindow (hwnd_dialog, SW_SHOWDEFAULT); + UpdateWindow (hwnd_dialog); + SetForegroundWindow (hwnd_dialog); + } + } + +// take the greater of all the available memory or half the total memory, +// but at least 8 Mb and no more than 16 Mb, unless they explicitly +// request otherwise + parms.memsize = lpBuffer.dwAvailPhys; + + if (parms.memsize < MINIMUM_WIN_MEMORY) + parms.memsize = MINIMUM_WIN_MEMORY; + + if (parms.memsize < (lpBuffer.dwTotalPhys >> 1)) + parms.memsize = lpBuffer.dwTotalPhys >> 1; + + if (parms.memsize > MAXIMUM_WIN_MEMORY) + parms.memsize = MAXIMUM_WIN_MEMORY; + + if (COM_CheckParm ("-heapsize")) + { + t = COM_CheckParm("-heapsize") + 1; + + if (t < com_argc) + parms.memsize = Q_atoi (com_argv[t]) * 1024; + } + + parms.membase = malloc (parms.memsize); + + if (!parms.membase) + Sys_Error ("Not enough memory free; check disk space\n"); + + Sys_PageIn (parms.membase, parms.memsize); + + tevent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (!tevent) + Sys_Error ("Couldn't create event"); + + if (isDedicated) + { + if (!AllocConsole ()) + { + Sys_Error ("Couldn't create dedicated server console"); + } + + hinput = GetStdHandle (STD_INPUT_HANDLE); + houtput = GetStdHandle (STD_OUTPUT_HANDLE); + + // give QHOST a chance to hook into the console + if ((t = COM_CheckParm ("-HFILE")) > 0) + { + if (t < com_argc) + hFile = (HANDLE)Q_atoi (com_argv[t+1]); + } + + if ((t = COM_CheckParm ("-HPARENT")) > 0) + { + if (t < com_argc) + heventParent = (HANDLE)Q_atoi (com_argv[t+1]); + } + + if ((t = COM_CheckParm ("-HCHILD")) > 0) + { + if (t < com_argc) + heventChild = (HANDLE)Q_atoi (com_argv[t+1]); + } + + InitConProc (hFile, heventParent, heventChild); + } + + Sys_Init (); + +// because sound is off until we become active + S_BlockSound (); + + Sys_Printf ("Host_Init\n"); + Host_Init (&parms); + + oldtime = Sys_FloatTime (); + + /* main window message loop */ + while (1) + { + if (isDedicated) + { + newtime = Sys_FloatTime (); + time = newtime - oldtime; + + while (time < sys_ticrate.value ) + { + Sys_Sleep(); + newtime = Sys_FloatTime (); + time = newtime - oldtime; + } + } + else + { + // yield the CPU for a little while when paused, minimized, or not the focus + if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing) + { + SleepUntilInput (PAUSE_SLEEP); + scr_skipupdate = 1; // no point in bothering to draw + } + else if (!ActiveApp && !DDActive) + { + SleepUntilInput (NOT_FOCUS_SLEEP); + } + + newtime = Sys_FloatTime (); + time = newtime - oldtime; + } + + Host_Frame (time); + oldtime = newtime; + } + + /* return success of application */ + return TRUE; +} + diff --git a/WinQuake/sys_wina.s b/WinQuake/sys_wina.s index e9ba618..de58d4c 100644 --- a/WinQuake/sys_wina.s +++ b/WinQuake/sys_wina.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // sys_wina.s // x86 assembly-language Win-dependent routines. diff --git a/WinQuake/sys_wind.c b/WinQuake/sys_wind.c index ccce22b..3002f57 100644 --- a/WinQuake/sys_wind.c +++ b/WinQuake/sys_wind.c @@ -1,325 +1,325 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sys_null.h -- null system driver to aid porting efforts - -#include "quakedef.h" -#include "winquake.h" -#include "errno.h" -#include -#include - - -/* -=============================================================================== - -FILE IO - -=============================================================================== -*/ - -#define MAX_HANDLES 10 -FILE *sys_handles[MAX_HANDLES]; - -int findhandle (void) -{ - int i; - - for (i=1 ; i +#include + + +/* +=============================================================================== + +FILE IO + +=============================================================================== +*/ + +#define MAX_HANDLES 10 +FILE *sys_handles[MAX_HANDLES]; + +int findhandle (void) +{ + int i; + + for (i=1 ; i width if displayed in a window - unsigned width; - unsigned height; - float aspect; // width / height -- < 0 is taller than wide - int numpages; - int recalc_refdef; // if true, recalc vid-based stuff - pixel_t *conbuffer; - int conrowbytes; - unsigned conwidth; - unsigned conheight; - int maxwarpwidth; - int maxwarpheight; - pixel_t *direct; // direct drawing to framebuffer, if not - // NULL -} viddef_t; - -extern viddef_t vid; // global video state -extern unsigned short d_8to16table[256]; -extern unsigned d_8to24table[256]; -extern void (*vid_menudrawfn)(void); -extern void (*vid_menukeyfn)(int key); - -void VID_SetPalette (unsigned char *palette); -// called at startup and after any gamma correction - -void VID_ShiftPalette (unsigned char *palette); -// called for bonus and pain flashes, and for underwater color changes - -void VID_Init (unsigned char *palette); -// Called at startup to set up translation tables, takes 256 8 bit RGB values -// the palette data will go away after the call, so it must be copied off if -// the video driver will need it again - -void VID_Shutdown (void); -// Called at shutdown - -void VID_Update (vrect_t *rects); -// flushes the given rectangles from the view buffer to the screen - -int VID_SetMode (int modenum, unsigned char *palette); -// sets the mode; only used by the Quake engine for resetting to mode 0 (the -// base mode) on memory allocation failures - -void VID_HandlePause (qboolean pause); -// called only on Win32, when pause happens, so the mouse can be released - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// vid.h -- video driver defs + +#define VID_CBITS 6 +#define VID_GRADES (1 << VID_CBITS) + +// a pixel can be one, two, or four bytes +typedef byte pixel_t; + +typedef struct vrect_s +{ + int x,y,width,height; + struct vrect_s *pnext; +} vrect_t; + +typedef struct +{ + pixel_t *buffer; // invisible buffer + pixel_t *colormap; // 256 * VID_GRADES size + unsigned short *colormap16; // 256 * VID_GRADES size + int fullbright; // index of first fullbright color + unsigned rowbytes; // may be > width if displayed in a window + unsigned width; + unsigned height; + float aspect; // width / height -- < 0 is taller than wide + int numpages; + int recalc_refdef; // if true, recalc vid-based stuff + pixel_t *conbuffer; + int conrowbytes; + unsigned conwidth; + unsigned conheight; + int maxwarpwidth; + int maxwarpheight; + pixel_t *direct; // direct drawing to framebuffer, if not + // NULL +} viddef_t; + +extern viddef_t vid; // global video state +extern unsigned short d_8to16table[256]; +extern unsigned d_8to24table[256]; +extern void (*vid_menudrawfn)(void); +extern void (*vid_menukeyfn)(int key); + +void VID_SetPalette (unsigned char *palette); +// called at startup and after any gamma correction + +void VID_ShiftPalette (unsigned char *palette); +// called for bonus and pain flashes, and for underwater color changes + +void VID_Init (unsigned char *palette); +// Called at startup to set up translation tables, takes 256 8 bit RGB values +// the palette data will go away after the call, so it must be copied off if +// the video driver will need it again + +void VID_Shutdown (void); +// Called at shutdown + +void VID_Update (vrect_t *rects); +// flushes the given rectangles from the view buffer to the screen + +int VID_SetMode (int modenum, unsigned char *palette); +// sets the mode; only used by the Quake engine for resetting to mode 0 (the +// base mode) on memory allocation failures + +void VID_HandlePause (qboolean pause); +// called only on Win32, when pause happens, so the mouse can be released + diff --git a/WinQuake/vid_dos.c b/WinQuake/vid_dos.c index bf4293f..519d9a0 100644 --- a/WinQuake/vid_dos.c +++ b/WinQuake/vid_dos.c @@ -1,778 +1,778 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// vid_dos.c: DOS-specific video routines -// - -#include -#include -#include -#include -#include -#include -#include - -#include "quakedef.h" -#include "d_local.h" -#include "dosisms.h" -#include "vid_dos.h" - -int vid_modenum; -vmode_t *pcurrentmode = NULL; -int vid_testingmode, vid_realmode; -double vid_testendtime; - -cvar_t vid_mode = {"vid_mode","0", false}; -cvar_t vid_wait = {"vid_wait","0"}; -cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; -cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; -cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; -cvar_t _vid_default_mode_win = {"_vid_default_mode_win","1", true}; -cvar_t vid_config_x = {"vid_config_x","800", true}; -cvar_t vid_config_y = {"vid_config_y","600", true}; -cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; -cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; -cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; -cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; -cvar_t block_switch = {"block_switch","0", true}; -cvar_t vid_window_x = {"vid_window_x", "0", true}; -cvar_t vid_window_y = {"vid_window_y", "0", true}; - -int d_con_indirect = 0; - -int numvidmodes; -vmode_t *pvidmodes; - -static int firstupdate = 1; - -extern regs_t regs; - -void VID_TestMode_f (void); -void VID_NumModes_f (void); -void VID_DescribeCurrentMode_f (void); -void VID_DescribeMode_f (void); -void VID_DescribeModes_f (void); - -byte vid_current_palette[768]; // save for mode changes - - -static qboolean nomodecheck = false; - -unsigned short d_8to16table[256]; // not used in 8 bpp mode -unsigned d_8to24table[256]; // not used in 8 bpp mode - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - - -/* -================ -VID_Init -================ -*/ -void VID_Init (unsigned char *palette) -{ - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_wait); - Cvar_RegisterVariable (&vid_nopageflip); - Cvar_RegisterVariable (&_vid_wait_override); - Cvar_RegisterVariable (&_vid_default_mode); - Cvar_RegisterVariable (&_vid_default_mode_win); - Cvar_RegisterVariable (&vid_config_x); - Cvar_RegisterVariable (&vid_config_y); - Cvar_RegisterVariable (&vid_stretch_by_2); - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&vid_fullscreen_mode); - Cvar_RegisterVariable (&vid_windowed_mode); - Cvar_RegisterVariable (&block_switch); - - Cmd_AddCommand ("vid_testmode", VID_TestMode_f); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); - -// set up the mode list; note that later inits link in their modes ahead of -// earlier ones, so the standard VGA modes are always first in the list. This -// is important because mode 0 must always be VGA mode 0x13 - if (!COM_CheckParm ("-stdvid")) - VID_InitExtra (); - VGA_Init (); - - vid_testingmode = 0; - - vid_modenum = vid_mode.value; - - VID_SetMode (vid_modenum, palette); - - vid_realmode = vid_modenum; - - vid_menudrawfn = VID_MenuDraw; - vid_menukeyfn = VID_MenuKey; -} - - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) -{ - vmode_t *pv; - - pv = pvidmodes; - if (!pv) - Sys_Error ("VID_GetModePtr: empty vid mode list"); - - while (modenum--) - { - pv = pv->pnext; - if (!pv) - Sys_Error ("VID_GetModePtr: corrupt vid mode list"); - } - - return pv; -} - -/* -================ -VID_NumModes -================ -*/ -int VID_NumModes () -{ - return (numvidmodes); -} - - -/* -================ -VID_ModeInfo -================ -*/ -char *VID_ModeInfo (int modenum, char **ppheader) -{ - static char *badmodestr = "Bad mode number"; - vmode_t *pv; - - pv = VID_GetModePtr (modenum); - - if (!pv) - { - if (ppheader) - *ppheader = NULL; - return badmodestr; - } - else - { - if (ppheader) - *ppheader = pv->header; - return pv->name; - } -} - - -/* -================ -VID_SetMode -================ -*/ -int VID_SetMode (int modenum, unsigned char *palette) -{ - int stat; - vmode_t *pnewmode, *poldmode; - - if ((modenum >= numvidmodes) || (modenum < 0)) - { - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - nomodecheck = true; - Con_Printf ("No such video mode: %d\n", modenum); - nomodecheck = false; - - if (pcurrentmode == NULL) - { - modenum = 0; // mode hasn't been set yet, so initialize to base - // mode since they gave us an invalid initial mode - } - else - { - return 0; - } - } - - pnewmode = VID_GetModePtr (modenum); - - if (pnewmode == pcurrentmode) - return 1; // already in the desired mode - -// initialize the new mode - poldmode = pcurrentmode; - pcurrentmode = pnewmode; - - vid.width = pcurrentmode->width; - vid.height = pcurrentmode->height; - vid.aspect = pcurrentmode->aspect; - vid.rowbytes = pcurrentmode->rowbytes; - - stat = (*pcurrentmode->setmode) (&vid, pcurrentmode); - - if (stat < 1) - { - if (stat == 0) - { - // real, hard failure that requires resetting the mode - if (!VID_SetMode (vid_modenum, palette)) // restore prior mode - Sys_Error ("VID_SetMode: Unable to set any mode, probably " - "because there's not enough memory available"); - Con_Printf ("Failed to set mode %d\n", modenum); - return 0; - } - else if (stat == -1) - { - // not enough memory; just put things back the way they were - pcurrentmode = poldmode; - vid.width = pcurrentmode->width; - vid.height = pcurrentmode->height; - vid.aspect = pcurrentmode->aspect; - vid.rowbytes = pcurrentmode->rowbytes; - return 0; - } - else - { - Sys_Error ("VID_SetMode: invalid setmode return code %d"); - } - } - - (*pcurrentmode->setpalette) (&vid, pcurrentmode, palette); - - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - nomodecheck = true; - Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); - nomodecheck = false; - - vid.recalc_refdef = 1; - - return 1; -} - - -/* -================ -VID_SetPalette -================ -*/ -void VID_SetPalette (unsigned char *palette) -{ - if (palette != vid_current_palette) - Q_memcpy(vid_current_palette, palette, 768); - (*pcurrentmode->setpalette)(&vid, pcurrentmode, vid_current_palette); -} - - -/* -================ -VID_ShiftPalette -================ -*/ -void VID_ShiftPalette (unsigned char *palette) -{ - - VID_SetPalette (palette); -} - - -/* -================ -VID_Shutdown -================ -*/ -void VID_Shutdown (void) -{ - - regs.h.ah = 0; - regs.h.al = 0x3; - dos_int86(0x10); - - vid_testingmode = 0; -} - - -/* -================ -VID_Update -================ -*/ -void VID_Update (vrect_t *rects) -{ - if (firstupdate && _vid_default_mode.value) - { - if(_vid_default_mode.value >= numvidmodes) - Cvar_SetValue ("_vid_default_mode", 0); - - firstupdate = 0; - Cvar_SetValue ("vid_mode", _vid_default_mode.value); - } - - (*pcurrentmode->swapbuffers)(&vid, pcurrentmode, rects); - - if (!nomodecheck) - { - if (vid_testingmode) - { - if (realtime >= vid_testendtime) - { - VID_SetMode (vid_realmode, vid_current_palette); - vid_testingmode = 0; - } - } - else - { - if (vid_mode.value != vid_realmode) - { - VID_SetMode ((int)vid_mode.value, vid_current_palette); - Cvar_SetValue ("vid_mode", (float)vid_modenum); - // so if mode set fails, we don't keep on - // trying to set that mode - vid_realmode = vid_modenum; - } - } - } -} - - -/* -================= -VID_NumModes_f -================= -*/ -void VID_NumModes_f (void) -{ - int nummodes; - - nummodes = VID_NumModes (); - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", VID_NumModes ()); - else - Con_Printf ("%d video modes are available\n", VID_NumModes ()); -} - - -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void VID_DescribeCurrentMode_f (void) -{ - Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); -} - - -/* -================= -VID_DescribeMode_f -================= -*/ -void VID_DescribeMode_f (void) -{ - int modenum; - - modenum = Q_atoi (Cmd_Argv(1)); - - Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL)); -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, nummodes; - char *pinfo, *pheader; - vmode_t *pv; - qboolean na; - - na = false; - - nummodes = VID_NumModes (); - for (i=0 ; iwidth, pv->height, pv->rowbytes, - (pv->numpages == 1) || vid_nopageflip.value)) - { - Con_Printf ("%2d: %s\n", i, pinfo); - } - else - { - Con_Printf ("**: %s\n", pinfo); - na = true; - } - } - - if (na) - { - Con_Printf ("\n[**: not enough system RAM for mode]\n"); - } -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) -{ - char *pinfo, *pheader; - vmode_t *pv; - - pv = VID_GetModePtr (mode); - pinfo = VID_ModeInfo (mode, &pheader); - - if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes, - (pv->numpages == 1) || vid_nopageflip.value)) - { - return pinfo; - } - else - { - return NULL; - } -} - - -/* -================= -VID_TestMode_f -================= -*/ -void VID_TestMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - if (VID_SetMode (modenum, vid_current_palette)) - { - vid_testingmode = 1; - testduration = Q_atof (Cmd_Argv(2)); - if (testduration == 0) - testduration = 5.0; - vid_testendtime = realtime + testduration; - } - } -} - - -/* -================ -D_BeginDirectRect -================ -*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ - - if (!vid.direct || !pcurrentmode) - return; - - if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) - return; - - if (width & 0x03) - return; - - (*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width, - height); -} - - -/* -================ -D_EndDirectRect -================ -*/ -void D_EndDirectRect (int x, int y, int width, int height) -{ - - if (!vid.direct || !pcurrentmode) - return; - - if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) - return; - - if ((width & 0x03) || (height & 0x03)) - return; - - (*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height); -} - - -//=========================================================================== - -extern void M_Menu_Options_f (void); -extern void M_Print (int cx, int cy, char *str); -extern void M_PrintWhite (int cx, int cy, char *str); -extern void M_DrawCharacter (int cx, int line, int num); -extern void M_DrawTransPic (int x, int y, qpic_t *pic); -extern void M_DrawPic (int x, int y, qpic_t *pic); - -static int vid_line, vid_wmodes, vid_column_size; - -typedef struct -{ - int modenum; - char *desc; - int iscur; -} modedesc_t; - -#define MAX_COLUMN_SIZE 11 - -#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) - -static modedesc_t modedescs[MAX_MODEDESCS]; - -/* -================ -VID_MenuDraw -================ -*/ -void VID_MenuDraw (void) -{ - qpic_t *p; - char *ptr; - int nummodes, i, j, column, row, dup; - char temp[100]; - - vid_wmodes = 0; - nummodes = VID_NumModes (); - - p = Draw_CachePic ("gfx/vidmodes.lmp"); - M_DrawPic ( (320-p->width)/2, 4, p); - - for (i=0 ; i= vid_wmodes) - vid_line = 0; - break; - - case K_LEFTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line -= vid_column_size; - - if (vid_line < 0) - { - vid_line += ((vid_wmodes + (vid_column_size - 1)) / - vid_column_size) * vid_column_size; - - while (vid_line >= vid_wmodes) - vid_line -= vid_column_size; - } - break; - - case K_RIGHTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line += vid_column_size; - - if (vid_line >= vid_wmodes) - { - vid_line -= ((vid_wmodes + (vid_column_size - 1)) / - vid_column_size) * vid_column_size; - - while (vid_line < 0) - vid_line += vid_column_size; - } - break; - - case K_ENTER: - S_LocalSound ("misc/menu1.wav"); - VID_SetMode (modedescs[vid_line].modenum, vid_current_palette); - break; - - case 'T': - case 't': - S_LocalSound ("misc/menu1.wav"); - if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette)) - { - vid_testingmode = 1; - vid_testendtime = realtime + 5.0; - } - break; - - case 'D': - case 'd': - S_LocalSound ("misc/menu1.wav"); - firstupdate = 0; - Cvar_SetValue ("_vid_default_mode", vid_modenum); - break; - - default: - break; - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// vid_dos.c: DOS-specific video routines +// + +#include +#include +#include +#include +#include +#include +#include + +#include "quakedef.h" +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" + +int vid_modenum; +vmode_t *pcurrentmode = NULL; +int vid_testingmode, vid_realmode; +double vid_testendtime; + +cvar_t vid_mode = {"vid_mode","0", false}; +cvar_t vid_wait = {"vid_wait","0"}; +cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; +cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; +cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; +cvar_t _vid_default_mode_win = {"_vid_default_mode_win","1", true}; +cvar_t vid_config_x = {"vid_config_x","800", true}; +cvar_t vid_config_y = {"vid_config_y","600", true}; +cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; +cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; +cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; +cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; +cvar_t block_switch = {"block_switch","0", true}; +cvar_t vid_window_x = {"vid_window_x", "0", true}; +cvar_t vid_window_y = {"vid_window_y", "0", true}; + +int d_con_indirect = 0; + +int numvidmodes; +vmode_t *pvidmodes; + +static int firstupdate = 1; + +extern regs_t regs; + +void VID_TestMode_f (void); +void VID_NumModes_f (void); +void VID_DescribeCurrentMode_f (void); +void VID_DescribeMode_f (void); +void VID_DescribeModes_f (void); + +byte vid_current_palette[768]; // save for mode changes + + +static qboolean nomodecheck = false; + +unsigned short d_8to16table[256]; // not used in 8 bpp mode +unsigned d_8to24table[256]; // not used in 8 bpp mode + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + + +/* +================ +VID_Init +================ +*/ +void VID_Init (unsigned char *palette) +{ + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&vid_wait); + Cvar_RegisterVariable (&vid_nopageflip); + Cvar_RegisterVariable (&_vid_wait_override); + Cvar_RegisterVariable (&_vid_default_mode); + Cvar_RegisterVariable (&_vid_default_mode_win); + Cvar_RegisterVariable (&vid_config_x); + Cvar_RegisterVariable (&vid_config_y); + Cvar_RegisterVariable (&vid_stretch_by_2); + Cvar_RegisterVariable (&_windowed_mouse); + Cvar_RegisterVariable (&vid_fullscreen_mode); + Cvar_RegisterVariable (&vid_windowed_mode); + Cvar_RegisterVariable (&block_switch); + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); + +// set up the mode list; note that later inits link in their modes ahead of +// earlier ones, so the standard VGA modes are always first in the list. This +// is important because mode 0 must always be VGA mode 0x13 + if (!COM_CheckParm ("-stdvid")) + VID_InitExtra (); + VGA_Init (); + + vid_testingmode = 0; + + vid_modenum = vid_mode.value; + + VID_SetMode (vid_modenum, palette); + + vid_realmode = vid_modenum; + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t *VID_GetModePtr (int modenum) +{ + vmode_t *pv; + + pv = pvidmodes; + if (!pv) + Sys_Error ("VID_GetModePtr: empty vid mode list"); + + while (modenum--) + { + pv = pv->pnext; + if (!pv) + Sys_Error ("VID_GetModePtr: corrupt vid mode list"); + } + + return pv; +} + +/* +================ +VID_NumModes +================ +*/ +int VID_NumModes () +{ + return (numvidmodes); +} + + +/* +================ +VID_ModeInfo +================ +*/ +char *VID_ModeInfo (int modenum, char **ppheader) +{ + static char *badmodestr = "Bad mode number"; + vmode_t *pv; + + pv = VID_GetModePtr (modenum); + + if (!pv) + { + if (ppheader) + *ppheader = NULL; + return badmodestr; + } + else + { + if (ppheader) + *ppheader = pv->header; + return pv->name; + } +} + + +/* +================ +VID_SetMode +================ +*/ +int VID_SetMode (int modenum, unsigned char *palette) +{ + int stat; + vmode_t *pnewmode, *poldmode; + + if ((modenum >= numvidmodes) || (modenum < 0)) + { + Cvar_SetValue ("vid_mode", (float)vid_modenum); + + nomodecheck = true; + Con_Printf ("No such video mode: %d\n", modenum); + nomodecheck = false; + + if (pcurrentmode == NULL) + { + modenum = 0; // mode hasn't been set yet, so initialize to base + // mode since they gave us an invalid initial mode + } + else + { + return 0; + } + } + + pnewmode = VID_GetModePtr (modenum); + + if (pnewmode == pcurrentmode) + return 1; // already in the desired mode + +// initialize the new mode + poldmode = pcurrentmode; + pcurrentmode = pnewmode; + + vid.width = pcurrentmode->width; + vid.height = pcurrentmode->height; + vid.aspect = pcurrentmode->aspect; + vid.rowbytes = pcurrentmode->rowbytes; + + stat = (*pcurrentmode->setmode) (&vid, pcurrentmode); + + if (stat < 1) + { + if (stat == 0) + { + // real, hard failure that requires resetting the mode + if (!VID_SetMode (vid_modenum, palette)) // restore prior mode + Sys_Error ("VID_SetMode: Unable to set any mode, probably " + "because there's not enough memory available"); + Con_Printf ("Failed to set mode %d\n", modenum); + return 0; + } + else if (stat == -1) + { + // not enough memory; just put things back the way they were + pcurrentmode = poldmode; + vid.width = pcurrentmode->width; + vid.height = pcurrentmode->height; + vid.aspect = pcurrentmode->aspect; + vid.rowbytes = pcurrentmode->rowbytes; + return 0; + } + else + { + Sys_Error ("VID_SetMode: invalid setmode return code %d"); + } + } + + (*pcurrentmode->setpalette) (&vid, pcurrentmode, palette); + + vid_modenum = modenum; + Cvar_SetValue ("vid_mode", (float)vid_modenum); + + nomodecheck = true; + Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); + nomodecheck = false; + + vid.recalc_refdef = 1; + + return 1; +} + + +/* +================ +VID_SetPalette +================ +*/ +void VID_SetPalette (unsigned char *palette) +{ + if (palette != vid_current_palette) + Q_memcpy(vid_current_palette, palette, 768); + (*pcurrentmode->setpalette)(&vid, pcurrentmode, vid_current_palette); +} + + +/* +================ +VID_ShiftPalette +================ +*/ +void VID_ShiftPalette (unsigned char *palette) +{ + + VID_SetPalette (palette); +} + + +/* +================ +VID_Shutdown +================ +*/ +void VID_Shutdown (void) +{ + + regs.h.ah = 0; + regs.h.al = 0x3; + dos_int86(0x10); + + vid_testingmode = 0; +} + + +/* +================ +VID_Update +================ +*/ +void VID_Update (vrect_t *rects) +{ + if (firstupdate && _vid_default_mode.value) + { + if(_vid_default_mode.value >= numvidmodes) + Cvar_SetValue ("_vid_default_mode", 0); + + firstupdate = 0; + Cvar_SetValue ("vid_mode", _vid_default_mode.value); + } + + (*pcurrentmode->swapbuffers)(&vid, pcurrentmode, rects); + + if (!nomodecheck) + { + if (vid_testingmode) + { + if (realtime >= vid_testendtime) + { + VID_SetMode (vid_realmode, vid_current_palette); + vid_testingmode = 0; + } + } + else + { + if (vid_mode.value != vid_realmode) + { + VID_SetMode ((int)vid_mode.value, vid_current_palette); + Cvar_SetValue ("vid_mode", (float)vid_modenum); + // so if mode set fails, we don't keep on + // trying to set that mode + vid_realmode = vid_modenum; + } + } + } +} + + +/* +================= +VID_NumModes_f +================= +*/ +void VID_NumModes_f (void) +{ + int nummodes; + + nummodes = VID_NumModes (); + if (nummodes == 1) + Con_Printf ("%d video mode is available\n", VID_NumModes ()); + else + Con_Printf ("%d video modes are available\n", VID_NumModes ()); +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void VID_DescribeCurrentMode_f (void) +{ + Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL)); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void VID_DescribeMode_f (void) +{ + int modenum; + + modenum = Q_atoi (Cmd_Argv(1)); + + Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL)); +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void VID_DescribeModes_f (void) +{ + int i, nummodes; + char *pinfo, *pheader; + vmode_t *pv; + qboolean na; + + na = false; + + nummodes = VID_NumModes (); + for (i=0 ; iwidth, pv->height, pv->rowbytes, + (pv->numpages == 1) || vid_nopageflip.value)) + { + Con_Printf ("%2d: %s\n", i, pinfo); + } + else + { + Con_Printf ("**: %s\n", pinfo); + na = true; + } + } + + if (na) + { + Con_Printf ("\n[**: not enough system RAM for mode]\n"); + } +} + + +/* +================= +VID_GetModeDescription +================= +*/ +char *VID_GetModeDescription (int mode) +{ + char *pinfo, *pheader; + vmode_t *pv; + + pv = VID_GetModePtr (mode); + pinfo = VID_ModeInfo (mode, &pheader); + + if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes, + (pv->numpages == 1) || vid_nopageflip.value)) + { + return pinfo; + } + else + { + return NULL; + } +} + + +/* +================= +VID_TestMode_f +================= +*/ +void VID_TestMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) + { + modenum = Q_atoi (Cmd_Argv(1)); + + if (VID_SetMode (modenum, vid_current_palette)) + { + vid_testingmode = 1; + testduration = Q_atof (Cmd_Argv(2)); + if (testduration == 0) + testduration = 5.0; + vid_testendtime = realtime + testduration; + } + } +} + + +/* +================ +D_BeginDirectRect +================ +*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ + + if (!vid.direct || !pcurrentmode) + return; + + if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) + return; + + if (width & 0x03) + return; + + (*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width, + height); +} + + +/* +================ +D_EndDirectRect +================ +*/ +void D_EndDirectRect (int x, int y, int width, int height) +{ + + if (!vid.direct || !pcurrentmode) + return; + + if ((width > 24) || (height > 24) || (width < 1) || (height < 1)) + return; + + if ((width & 0x03) || (height & 0x03)) + return; + + (*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height); +} + + +//=========================================================================== + +extern void M_Menu_Options_f (void); +extern void M_Print (int cx, int cy, char *str); +extern void M_PrintWhite (int cx, int cy, char *str); +extern void M_DrawCharacter (int cx, int line, int num); +extern void M_DrawTransPic (int x, int y, qpic_t *pic); +extern void M_DrawPic (int x, int y, qpic_t *pic); + +static int vid_line, vid_wmodes, vid_column_size; + +typedef struct +{ + int modenum; + char *desc; + int iscur; +} modedesc_t; + +#define MAX_COLUMN_SIZE 11 + +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +static modedesc_t modedescs[MAX_MODEDESCS]; + +/* +================ +VID_MenuDraw +================ +*/ +void VID_MenuDraw (void) +{ + qpic_t *p; + char *ptr; + int nummodes, i, j, column, row, dup; + char temp[100]; + + vid_wmodes = 0; + nummodes = VID_NumModes (); + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + for (i=0 ; i= vid_wmodes) + vid_line = 0; + break; + + case K_LEFTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line -= vid_column_size; + + if (vid_line < 0) + { + vid_line += ((vid_wmodes + (vid_column_size - 1)) / + vid_column_size) * vid_column_size; + + while (vid_line >= vid_wmodes) + vid_line -= vid_column_size; + } + break; + + case K_RIGHTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line += vid_column_size; + + if (vid_line >= vid_wmodes) + { + vid_line -= ((vid_wmodes + (vid_column_size - 1)) / + vid_column_size) * vid_column_size; + + while (vid_line < 0) + vid_line += vid_column_size; + } + break; + + case K_ENTER: + S_LocalSound ("misc/menu1.wav"); + VID_SetMode (modedescs[vid_line].modenum, vid_current_palette); + break; + + case 'T': + case 't': + S_LocalSound ("misc/menu1.wav"); + if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette)) + { + vid_testingmode = 1; + vid_testendtime = realtime + 5.0; + } + break; + + case 'D': + case 'd': + S_LocalSound ("misc/menu1.wav"); + firstupdate = 0; + Cvar_SetValue ("_vid_default_mode", vid_modenum); + break; + + default: + break; + } +} + diff --git a/WinQuake/vid_dos.h b/WinQuake/vid_dos.h index 4740e59..a622dcb 100644 --- a/WinQuake/vid_dos.h +++ b/WinQuake/vid_dos.h @@ -1,83 +1,83 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// vid_dos.h: header file for DOS-specific video stuff - -typedef struct vmode_s { - struct vmode_s *pnext; - char *name; - char *header; - unsigned width; - unsigned height; - float aspect; - unsigned rowbytes; - int planar; - int numpages; - void *pextradata; - int (*setmode)(viddef_t *vid, struct vmode_s *pcurrentmode); - void (*swapbuffers)(viddef_t *vid, struct vmode_s *pcurrentmode, - vrect_t *rects); - void (*setpalette)(viddef_t *vid, struct vmode_s *pcurrentmode, - unsigned char *palette); - void (*begindirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode, - int x, int y, byte *pbitmap, int width, - int height); - void (*enddirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode, - int x, int y, int width, int height); -} vmode_t; - -// vid_wait settings -#define VID_WAIT_NONE 0 -#define VID_WAIT_VSYNC 1 -#define VID_WAIT_DISPLAY_ENABLE 2 - -extern int numvidmodes; -extern vmode_t *pvidmodes; - -extern int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; -extern byte *VGA_pagebase; -extern vmode_t *VGA_pcurmode; - -extern cvar_t vid_wait; -extern cvar_t vid_nopageflip; -extern cvar_t _vid_wait_override; - -extern unsigned char colormap256[32][256]; - -extern void *vid_surfcache; -extern int vid_surfcachesize; - -void VGA_Init (void); -void VID_InitVESA (void); -void VID_InitExtra (void); -void VGA_WaitVsync (void); -void VGA_ClearVideoMem (int planar); -void VGA_SetPalette(viddef_t *vid, vmode_t *pcurrentmode, unsigned char *pal); -void VGA_SwapBuffersCopy (viddef_t *vid, vmode_t *pcurrentmode, - vrect_t *rects); -qboolean VGA_FreeAndAllocVidbuffer (viddef_t *vid, int allocnewbuffer); -qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes, - int allocnewbuffer); -void VGA_BeginDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x, - int y, byte *pbitmap, int width, int height); -void VGA_EndDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x, - int y, int width, int height); -void VGA_UpdateLinearScreen (void *srcptr, void *destptr, int width, - int height, int srcrowbytes, int destrowbytes); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// vid_dos.h: header file for DOS-specific video stuff + +typedef struct vmode_s { + struct vmode_s *pnext; + char *name; + char *header; + unsigned width; + unsigned height; + float aspect; + unsigned rowbytes; + int planar; + int numpages; + void *pextradata; + int (*setmode)(viddef_t *vid, struct vmode_s *pcurrentmode); + void (*swapbuffers)(viddef_t *vid, struct vmode_s *pcurrentmode, + vrect_t *rects); + void (*setpalette)(viddef_t *vid, struct vmode_s *pcurrentmode, + unsigned char *palette); + void (*begindirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode, + int x, int y, byte *pbitmap, int width, + int height); + void (*enddirectrect)(viddef_t *vid, struct vmode_s *pcurrentmode, + int x, int y, int width, int height); +} vmode_t; + +// vid_wait settings +#define VID_WAIT_NONE 0 +#define VID_WAIT_VSYNC 1 +#define VID_WAIT_DISPLAY_ENABLE 2 + +extern int numvidmodes; +extern vmode_t *pvidmodes; + +extern int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; +extern byte *VGA_pagebase; +extern vmode_t *VGA_pcurmode; + +extern cvar_t vid_wait; +extern cvar_t vid_nopageflip; +extern cvar_t _vid_wait_override; + +extern unsigned char colormap256[32][256]; + +extern void *vid_surfcache; +extern int vid_surfcachesize; + +void VGA_Init (void); +void VID_InitVESA (void); +void VID_InitExtra (void); +void VGA_WaitVsync (void); +void VGA_ClearVideoMem (int planar); +void VGA_SetPalette(viddef_t *vid, vmode_t *pcurrentmode, unsigned char *pal); +void VGA_SwapBuffersCopy (viddef_t *vid, vmode_t *pcurrentmode, + vrect_t *rects); +qboolean VGA_FreeAndAllocVidbuffer (viddef_t *vid, int allocnewbuffer); +qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes, + int allocnewbuffer); +void VGA_BeginDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x, + int y, byte *pbitmap, int width, int height); +void VGA_EndDirectRect (viddef_t *vid, struct vmode_s *pcurrentmode, int x, + int y, int width, int height); +void VGA_UpdateLinearScreen (void *srcptr, void *destptr, int width, + int height, int srcrowbytes, int destrowbytes); + diff --git a/WinQuake/vid_ext.c b/WinQuake/vid_ext.c index 4188e2b..c12374c 100644 --- a/WinQuake/vid_ext.c +++ b/WinQuake/vid_ext.c @@ -1,795 +1,795 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// vid_ext.c: extended video modes -// in this implementation, VESA-specific DOS video stuff -// - -// TODO: make dependencies on vid_vga.c explicit or eliminate them - -#include -#include - -#include "quakedef.h" -#include "d_local.h" -#include "dosisms.h" -#include "vid_dos.h" -#include - -#define MODE_SUPPORTED_IN_HW 0x0001 -#define COLOR_MODE 0x0008 -#define GRAPHICS_MODE 0x0010 -#define VGA_INCOMPATIBLE 0x0020 -#define LINEAR_FRAME_BUFFER 0x0080 - -#define LINEAR_MODE 0x4000 - -#define VESA_DONT_WAIT_VSYNC 0 // when page flipping -#define VESA_WAIT_VSYNC 0x80 - -#define MAX_VESA_MODES 30 // we'll just take the first 30 if there - // are more -typedef struct { - int pages[3]; // either 2 or 3 is valid - int vesamode; // LINEAR_MODE set if linear mode - void *plinearmem; // linear address of start of frame buffer - qboolean vga_incompatible; -} vesa_extra_t; - -static vmode_t vesa_modes[MAX_VESA_MODES] = - {{NULL, NULL, " ********* VESA modes ********* "}}; -static vesa_extra_t vesa_extra[MAX_VESA_MODES]; -static char names[MAX_VESA_MODES][10]; - -extern regs_t regs; - -static int VID_currentpage; -static int VID_displayedpage; -static int *VID_pagelist; -static byte *VID_membase; -static int VID_banked; - -typedef struct -{ - int modenum; - int mode_attributes; - int winasegment; - int winbsegment; - int bytes_per_scanline; // bytes per logical scanline (+16) - int win; // window number (A=0, B=1) - int win_size; // window size (+6) - int granularity; // how finely i can set the window in vid mem (+4) - int width, height; // displayed width and height (+18, +20) - int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25) - int bytes_per_pixel; // er, better be 1, 2, or 4 - int memory_model; // and better be 4 or 6, packed or direct color (+27) - int num_pages; // number of complete frame buffer pages (+29) - int red_width; // the # of bits in the red component (+31) - int red_pos; // the bit position of the red component (+32) - int green_width; // etc.. (+33) - int green_pos; // (+34) - int blue_width; // (+35) - int blue_pos; // (+36) - int pptr; - int pagesize; - int numpages; -} modeinfo_t; - -static modeinfo_t modeinfo; - -// all bytes to avoid problems with compiler field packing -typedef struct vbeinfoblock_s { - byte VbeSignature[4]; - byte VbeVersion[2]; - byte OemStringPtr[4]; - byte Capabilities[4]; - byte VideoModePtr[4]; - byte TotalMemory[2]; - byte OemSoftwareRev[2]; - byte OemVendorNamePtr[4]; - byte OemProductNamePtr[4]; - byte OemProductRevPtr[4]; - byte Reserved[222]; - byte OemData[256]; -} vbeinfoblock_t; - -static int totalvidmem; -static byte *ppal; -qboolean vsync_exists, de_exists; - -qboolean VID_ExtraGetModeInfo(int modenum); -int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode); -void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode, - vrect_t *rects); - - -/* -================ -VGA_BankedBeginDirectRect -================ -*/ -void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, - int x, int y, byte *pbitmap, int width, int height) -{ - - if (!lvid->direct) - return; - - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_displayedpage; - dos_int86(0x10); - - VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height); - - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_currentpage; - dos_int86(0x10); -} - - -/* -================ -VGA_BankedEndDirectRect -================ -*/ -void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, - int x, int y, int width, int height) -{ - - if (!lvid->direct) - return; - - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_displayedpage; - dos_int86(0x10); - - VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height); - - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_currentpage; - dos_int86(0x10); -} - - -/* -================ -VID_SetVESAPalette -================ -*/ -void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode, - unsigned char *pal) -{ - int i; - byte *pp; - - UNUSED(lvid); - UNUSED(pcurrentmode); - - pp = ppal; - - for (i=0 ; i<256 ; i++) - { - pp[2] = pal[0] >> 2; - pp[1] = pal[1] >> 2; - pp[0] = pal[2] >> 2; - pp += 4; - pal += 3; - } - - regs.x.ax = 0x4F09; - regs.x.bx = 0; - regs.x.cx = 256; - regs.x.dx = 0; - regs.x.es = ptr2real(ppal) >> 4; - regs.x.di = ptr2real(ppal) & 0xf; - dos_int86(0x10); - - if (regs.x.ax != 0x4f) - Sys_Error ("Unable to load VESA palette\n"); -} - - - - -/* -================ -VID_ExtraFarToLinear -================ -*/ -void *VID_ExtraFarToLinear (void *ptr) -{ - int temp; - - temp = (int)ptr; - return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF)); -} - - -/* -================ -VID_ExtraWaitDisplayEnable -================ -*/ -void VID_ExtraWaitDisplayEnable () -{ - while ((inportb (0x3DA) & 0x01) == 1) - ; -} - - -/* -================ -VID_ExtraVidLookForState -================ -*/ -qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask) -{ - int i; - double starttime, time; - - starttime = Sys_FloatTime (); - - do - { - for (i=0 ; i<100000 ; i++) - { - if ((inportb (0x3DA) & mask) == state) - return true; - } - - time = Sys_FloatTime (); - } while ((time - starttime) < 0.1); - - return false; -} - - -/* -================ -VID_ExtraStateFound -================ -*/ -qboolean VID_ExtraStateFound (unsigned state) -{ - int i, workingstate; - - workingstate = 0; - - for (i=0 ; i<10 ; i++) - { - if (!VID_ExtraVidLookForState(workingstate, state)) - { - return false; - } - - workingstate ^= state; - } - - return true; -} - - -/* -================ -VID_InitExtra -================ -*/ -void VID_InitExtra (void) -{ - int nummodes; - short *pmodenums; - vbeinfoblock_t *pinfoblock; - __dpmi_meminfo phys_mem_info; - - pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t)); - - *(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24); - -// see if VESA support is available - regs.x.ax = 0x4f00; - regs.x.es = ptr2real(pinfoblock) >> 4; - regs.x.di = ptr2real(pinfoblock) & 0xf; - dos_int86(0x10); - - if (regs.x.ax != 0x4f) - return; // no VESA support - - if (pinfoblock->VbeVersion[1] < 0x02) - return; // not VESA 2.0 or greater - - Con_Printf ("VESA 2.0 compliant adapter:\n%s\n", - VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0])); - - totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16; - - pmodenums = (short *) - VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]); - -// find 8 bit modes until we either run out of space or run out of modes - nummodes = 0; - - while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES)) - { - if (VID_ExtraGetModeInfo (*pmodenums)) - { - vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1]; - if (modeinfo.width > 999) - { - if (modeinfo.height > 999) - { - sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width, - modeinfo.height); - names[nummodes][9] = 0; - } - else - { - sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width, - modeinfo.height); - names[nummodes][8] = 0; - } - } - else - { - if (modeinfo.height > 999) - { - sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width, - modeinfo.height); - names[nummodes][8] = 0; - } - else - { - sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width, - modeinfo.height); - names[nummodes][7] = 0; - } - } - - vesa_modes[nummodes].name = &names[nummodes][0]; - vesa_modes[nummodes].width = modeinfo.width; - vesa_modes[nummodes].height = modeinfo.height; - vesa_modes[nummodes].aspect = - ((float)modeinfo.height / (float)modeinfo.width) * - (320.0 / 240.0); - vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline; - vesa_modes[nummodes].planar = 0; - vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; - vesa_modes[nummodes].setmode = VID_ExtraInitMode; - vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers; - vesa_modes[nummodes].setpalette = VID_SetVESAPalette; - - if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER) - { - // add linear bit to mode for linear modes - vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE; - vesa_extra[nummodes].pages[0] = 0; - vesa_extra[nummodes].pages[1] = modeinfo.pagesize; - vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; - vesa_modes[nummodes].numpages = modeinfo.numpages; - - vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect; - vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect; - - phys_mem_info.address = (int)modeinfo.pptr; - phys_mem_info.size = 0x400000; - - if (__dpmi_physical_address_mapping(&phys_mem_info)) - goto NextMode; - - vesa_extra[nummodes].plinearmem = - real2ptr (phys_mem_info.address); - } - else - { - // banked at 0xA0000 - vesa_extra[nummodes].vesamode = modeinfo.modenum; - vesa_extra[nummodes].pages[0] = 0; - vesa_extra[nummodes].plinearmem = - real2ptr(modeinfo.winasegment<<4); - - vesa_modes[nummodes].begindirectrect = - VGA_BankedBeginDirectRect; - vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect; - vesa_extra[nummodes].pages[1] = modeinfo.pagesize; - vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; - vesa_modes[nummodes].numpages = modeinfo.numpages; - } - - vesa_extra[nummodes].vga_incompatible = - modeinfo.mode_attributes & VGA_INCOMPATIBLE; - - nummodes++; - } -NextMode: - pmodenums++; - } - -// add the VESA modes at the start of the mode list (if there are any) - if (nummodes) - { - vesa_modes[nummodes-1].pnext = pvidmodes; - pvidmodes = &vesa_modes[0]; - numvidmodes += nummodes; - ppal = dos_getmemory(256*4); - } - - dos_freememory(pinfoblock); -} - - -/* -================ -VID_ExtraGetModeInfo -================ -*/ -qboolean VID_ExtraGetModeInfo(int modenum) -{ - char *infobuf; - int numimagepages; - - infobuf = dos_getmemory(256); - - regs.x.ax = 0x4f01; - regs.x.cx = modenum; - regs.x.es = ptr2real(infobuf) >> 4; - regs.x.di = ptr2real(infobuf) & 0xf; - dos_int86(0x10); - if (regs.x.ax != 0x4f) - { - return false; - } - else - { - modeinfo.modenum = modenum; - modeinfo.bits_per_pixel = *(char*)(infobuf+25); - modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; - modeinfo.width = *(short*)(infobuf+18); - modeinfo.height = *(short*)(infobuf+20); - - // we do only 8-bpp in software - if ((modeinfo.bits_per_pixel != 8) || - (modeinfo.bytes_per_pixel != 1) || - (modeinfo.width > MAXWIDTH) || - (modeinfo.height > MAXHEIGHT)) - { - return false; - } - - modeinfo.mode_attributes = *(short*)infobuf; - - // we only want color graphics modes that are supported by the hardware - if ((modeinfo.mode_attributes & - (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) != - (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) - { - return false; - } - - // we only work with linear frame buffers, except for 320x200, which can - // effectively be linear when banked at 0xA000 - if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)) - { - if ((modeinfo.width != 320) || (modeinfo.height != 200)) - return false; - } - - modeinfo.bytes_per_scanline = *(short*)(infobuf+16); - - modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height; - - if (modeinfo.pagesize > totalvidmem) - return false; - - // force to one page if the adapter reports it doesn't support more pages - // than that, no matter how much memory it has--it may not have hardware - // support for page flipping - numimagepages = *(unsigned char *)(infobuf+29); - - if (numimagepages <= 0) - { - // wrong, but there seems to be an ATI VESA driver that reports 0 - modeinfo.numpages = 1; - } - else if (numimagepages < 3) - { - modeinfo.numpages = numimagepages; - } - else - { - modeinfo.numpages = 3; - } - - if (*(char*)(infobuf+2) & 5) - { - modeinfo.winasegment = *(unsigned short*)(infobuf+8); - modeinfo.win = 0; - } - else if (*(char*)(infobuf+3) & 5) - { - modeinfo.winbsegment = *(unsigned short*)(infobuf+8); - modeinfo.win = 1; - } - modeinfo.granularity = *(short*)(infobuf+4) * 1024; - modeinfo.win_size = *(short*)(infobuf+6) * 1024; - modeinfo.bits_per_pixel = *(char*)(infobuf+25); - modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; - modeinfo.memory_model = *(unsigned char*)(infobuf+27); - modeinfo.num_pages = *(char*)(infobuf+29) + 1; - - modeinfo.red_width = *(char*)(infobuf+31); - modeinfo.red_pos = *(char*)(infobuf+32); - modeinfo.green_width = *(char*)(infobuf+33); - modeinfo.green_pos = *(char*)(infobuf+34); - modeinfo.blue_width = *(char*)(infobuf+35); - modeinfo.blue_pos = *(char*)(infobuf+36); - - modeinfo.pptr = *(long *)(infobuf+40); - -#if 0 - printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum); - printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes); - printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2)); - printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3)); - printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment); - printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment); - printf(" bytes per scanline = %d\n", - modeinfo.bytes_per_scanline); - printf(" width = %d, height = %d\n", modeinfo.width, - modeinfo.height); - printf(" win = %c\n", 'A' + modeinfo.win); - printf(" win granularity = %d\n", modeinfo.granularity); - printf(" win size = %d\n", modeinfo.win_size); - printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel); - printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel); - printf(" memory model = 0x%x\n", modeinfo.memory_model); - printf(" num pages = %d\n", modeinfo.num_pages); - printf(" red width = %d\n", modeinfo.red_width); - printf(" red pos = %d\n", modeinfo.red_pos); - printf(" green width = %d\n", modeinfo.green_width); - printf(" green pos = %d\n", modeinfo.green_pos); - printf(" blue width = %d\n", modeinfo.blue_width); - printf(" blue pos = %d\n", modeinfo.blue_pos); - printf(" phys mem = %x\n", modeinfo.pptr); -#endif - } - - dos_freememory(infobuf); - - return true; -} - - -/* -================ -VID_ExtraInitMode -================ -*/ -int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode) -{ - vesa_extra_t *pextra; - int pageoffset; - - pextra = pcurrentmode->pextradata; - - if (vid_nopageflip.value) - lvid->numpages = 1; - else - lvid->numpages = pcurrentmode->numpages; - -// clean up any old vid buffer lying around, alloc new if needed - if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1)) - return -1; // memory alloc failed - -// clear the screen and wait for the next frame. VGA_pcurmode, which -// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is -// always the first mode set in a session - if (VGA_pcurmode) - VGA_ClearVideoMem (VGA_pcurmode->planar); - -// set the mode - regs.x.ax = 0x4f02; - regs.x.bx = pextra->vesamode; - dos_int86(0x10); - - if (regs.x.ax != 0x4f) - return 0; - - VID_banked = !(pextra->vesamode & LINEAR_MODE); - VID_membase = pextra->plinearmem; - VGA_width = lvid->width; - VGA_height = lvid->height; - VGA_rowbytes = lvid->rowbytes; - - lvid->colormap = host_colormap; - - VID_pagelist = &pextra->pages[0]; - -// wait for display enable by default only when triple-buffering on a VGA- -// compatible machine that actually has a functioning display enable status - vsync_exists = VID_ExtraStateFound (0x08); - de_exists = VID_ExtraStateFound (0x01); - - if (!pextra->vga_incompatible && - (lvid->numpages == 3) && - de_exists && - (_vid_wait_override.value == 0.0)) - { - Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE); - - VID_displayedpage = 0; - VID_currentpage = 1; - } - else - { - if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0)) - { - Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); - VID_displayedpage = VID_currentpage = 0; - } - else - { - Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); - - VID_displayedpage = 0; - - if (lvid->numpages > 1) - VID_currentpage = 1; - else - VID_currentpage = 0; - } - } - -// TODO: really should be a call to a function - pageoffset = VID_pagelist[VID_displayedpage]; - - regs.x.ax = 0x4f07; - regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible - regs.x.cx = pageoffset % VGA_rowbytes; - regs.x.dx = pageoffset / VGA_rowbytes; - dos_int86(0x10); - - if (VID_banked) - { - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_currentpage; - dos_int86(0x10); - - VGA_pagebase = VID_membase; - } - else - { - VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage]; - } - - if (lvid->numpages > 1) - { - lvid->buffer = VGA_pagebase; - lvid->conbuffer = lvid->buffer; - } - else - { - lvid->rowbytes = lvid->width; - } - - lvid->direct = VGA_pagebase; - lvid->conrowbytes = lvid->rowbytes; - lvid->conwidth = lvid->width; - lvid->conheight = lvid->height; - - lvid->maxwarpwidth = WARP_WIDTH; - lvid->maxwarpheight = WARP_HEIGHT; - - VGA_pcurmode = pcurrentmode; - - D_InitCaches (vid_surfcache, vid_surfcachesize); - - return 1; -} - - -/* -================ -VID_ExtraSwapBuffers -================ -*/ -void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, - vrect_t *rects) -{ - int pageoffset; - - UNUSED(rects); - UNUSED(pcurrentmode); - - pageoffset = VID_pagelist[VID_currentpage]; - -// display the newly finished page - if (lvid->numpages > 1) - { - // page flipped - regs.x.ax = 0x4f07; - - if (vid_wait.value != VID_WAIT_VSYNC) - { - if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists) - VID_ExtraWaitDisplayEnable (); - - regs.x.bx = VESA_DONT_WAIT_VSYNC; - } - else - { - regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait - } - - regs.x.cx = pageoffset % VGA_rowbytes; - regs.x.dx = pageoffset / VGA_rowbytes; - dos_int86(0x10); - - VID_displayedpage = VID_currentpage; - if (++VID_currentpage >= lvid->numpages) - VID_currentpage = 0; - - // - // set the new write window if this is a banked mode; otherwise, set the - // new address to which to write - // - if (VID_banked) - { - regs.x.ax = 0x4f05; - regs.x.bx = 0; - regs.x.dx = VID_currentpage; - dos_int86(0x10); - } - else - { - lvid->direct = lvid->buffer; // direct drawing goes to the - // currently displayed page - lvid->buffer = VID_membase + VID_pagelist[VID_currentpage]; - lvid->conbuffer = lvid->buffer; - } - - VGA_pagebase = lvid->buffer; - } - else - { - // non-page-flipped - if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC)) - { - VGA_WaitVsync (); - } - - while (rects) - { - VGA_UpdateLinearScreen ( - lvid->buffer + rects->x + (rects->y * lvid->rowbytes), - VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), - rects->width, - rects->height, - lvid->rowbytes, - VGA_rowbytes); - - rects = rects->pnext; - } - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// vid_ext.c: extended video modes +// in this implementation, VESA-specific DOS video stuff +// + +// TODO: make dependencies on vid_vga.c explicit or eliminate them + +#include +#include + +#include "quakedef.h" +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" +#include + +#define MODE_SUPPORTED_IN_HW 0x0001 +#define COLOR_MODE 0x0008 +#define GRAPHICS_MODE 0x0010 +#define VGA_INCOMPATIBLE 0x0020 +#define LINEAR_FRAME_BUFFER 0x0080 + +#define LINEAR_MODE 0x4000 + +#define VESA_DONT_WAIT_VSYNC 0 // when page flipping +#define VESA_WAIT_VSYNC 0x80 + +#define MAX_VESA_MODES 30 // we'll just take the first 30 if there + // are more +typedef struct { + int pages[3]; // either 2 or 3 is valid + int vesamode; // LINEAR_MODE set if linear mode + void *plinearmem; // linear address of start of frame buffer + qboolean vga_incompatible; +} vesa_extra_t; + +static vmode_t vesa_modes[MAX_VESA_MODES] = + {{NULL, NULL, " ********* VESA modes ********* "}}; +static vesa_extra_t vesa_extra[MAX_VESA_MODES]; +static char names[MAX_VESA_MODES][10]; + +extern regs_t regs; + +static int VID_currentpage; +static int VID_displayedpage; +static int *VID_pagelist; +static byte *VID_membase; +static int VID_banked; + +typedef struct +{ + int modenum; + int mode_attributes; + int winasegment; + int winbsegment; + int bytes_per_scanline; // bytes per logical scanline (+16) + int win; // window number (A=0, B=1) + int win_size; // window size (+6) + int granularity; // how finely i can set the window in vid mem (+4) + int width, height; // displayed width and height (+18, +20) + int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25) + int bytes_per_pixel; // er, better be 1, 2, or 4 + int memory_model; // and better be 4 or 6, packed or direct color (+27) + int num_pages; // number of complete frame buffer pages (+29) + int red_width; // the # of bits in the red component (+31) + int red_pos; // the bit position of the red component (+32) + int green_width; // etc.. (+33) + int green_pos; // (+34) + int blue_width; // (+35) + int blue_pos; // (+36) + int pptr; + int pagesize; + int numpages; +} modeinfo_t; + +static modeinfo_t modeinfo; + +// all bytes to avoid problems with compiler field packing +typedef struct vbeinfoblock_s { + byte VbeSignature[4]; + byte VbeVersion[2]; + byte OemStringPtr[4]; + byte Capabilities[4]; + byte VideoModePtr[4]; + byte TotalMemory[2]; + byte OemSoftwareRev[2]; + byte OemVendorNamePtr[4]; + byte OemProductNamePtr[4]; + byte OemProductRevPtr[4]; + byte Reserved[222]; + byte OemData[256]; +} vbeinfoblock_t; + +static int totalvidmem; +static byte *ppal; +qboolean vsync_exists, de_exists; + +qboolean VID_ExtraGetModeInfo(int modenum); +int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode); +void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode, + vrect_t *rects); + + +/* +================ +VGA_BankedBeginDirectRect +================ +*/ +void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, + int x, int y, byte *pbitmap, int width, int height) +{ + + if (!lvid->direct) + return; + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_displayedpage; + dos_int86(0x10); + + VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height); + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86(0x10); +} + + +/* +================ +VGA_BankedEndDirectRect +================ +*/ +void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, + int x, int y, int width, int height) +{ + + if (!lvid->direct) + return; + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_displayedpage; + dos_int86(0x10); + + VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height); + + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86(0x10); +} + + +/* +================ +VID_SetVESAPalette +================ +*/ +void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode, + unsigned char *pal) +{ + int i; + byte *pp; + + UNUSED(lvid); + UNUSED(pcurrentmode); + + pp = ppal; + + for (i=0 ; i<256 ; i++) + { + pp[2] = pal[0] >> 2; + pp[1] = pal[1] >> 2; + pp[0] = pal[2] >> 2; + pp += 4; + pal += 3; + } + + regs.x.ax = 0x4F09; + regs.x.bx = 0; + regs.x.cx = 256; + regs.x.dx = 0; + regs.x.es = ptr2real(ppal) >> 4; + regs.x.di = ptr2real(ppal) & 0xf; + dos_int86(0x10); + + if (regs.x.ax != 0x4f) + Sys_Error ("Unable to load VESA palette\n"); +} + + + + +/* +================ +VID_ExtraFarToLinear +================ +*/ +void *VID_ExtraFarToLinear (void *ptr) +{ + int temp; + + temp = (int)ptr; + return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF)); +} + + +/* +================ +VID_ExtraWaitDisplayEnable +================ +*/ +void VID_ExtraWaitDisplayEnable () +{ + while ((inportb (0x3DA) & 0x01) == 1) + ; +} + + +/* +================ +VID_ExtraVidLookForState +================ +*/ +qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask) +{ + int i; + double starttime, time; + + starttime = Sys_FloatTime (); + + do + { + for (i=0 ; i<100000 ; i++) + { + if ((inportb (0x3DA) & mask) == state) + return true; + } + + time = Sys_FloatTime (); + } while ((time - starttime) < 0.1); + + return false; +} + + +/* +================ +VID_ExtraStateFound +================ +*/ +qboolean VID_ExtraStateFound (unsigned state) +{ + int i, workingstate; + + workingstate = 0; + + for (i=0 ; i<10 ; i++) + { + if (!VID_ExtraVidLookForState(workingstate, state)) + { + return false; + } + + workingstate ^= state; + } + + return true; +} + + +/* +================ +VID_InitExtra +================ +*/ +void VID_InitExtra (void) +{ + int nummodes; + short *pmodenums; + vbeinfoblock_t *pinfoblock; + __dpmi_meminfo phys_mem_info; + + pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t)); + + *(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24); + +// see if VESA support is available + regs.x.ax = 0x4f00; + regs.x.es = ptr2real(pinfoblock) >> 4; + regs.x.di = ptr2real(pinfoblock) & 0xf; + dos_int86(0x10); + + if (regs.x.ax != 0x4f) + return; // no VESA support + + if (pinfoblock->VbeVersion[1] < 0x02) + return; // not VESA 2.0 or greater + + Con_Printf ("VESA 2.0 compliant adapter:\n%s\n", + VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0])); + + totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16; + + pmodenums = (short *) + VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]); + +// find 8 bit modes until we either run out of space or run out of modes + nummodes = 0; + + while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES)) + { + if (VID_ExtraGetModeInfo (*pmodenums)) + { + vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1]; + if (modeinfo.width > 999) + { + if (modeinfo.height > 999) + { + sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width, + modeinfo.height); + names[nummodes][9] = 0; + } + else + { + sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width, + modeinfo.height); + names[nummodes][8] = 0; + } + } + else + { + if (modeinfo.height > 999) + { + sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width, + modeinfo.height); + names[nummodes][8] = 0; + } + else + { + sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width, + modeinfo.height); + names[nummodes][7] = 0; + } + } + + vesa_modes[nummodes].name = &names[nummodes][0]; + vesa_modes[nummodes].width = modeinfo.width; + vesa_modes[nummodes].height = modeinfo.height; + vesa_modes[nummodes].aspect = + ((float)modeinfo.height / (float)modeinfo.width) * + (320.0 / 240.0); + vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline; + vesa_modes[nummodes].planar = 0; + vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; + vesa_modes[nummodes].setmode = VID_ExtraInitMode; + vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers; + vesa_modes[nummodes].setpalette = VID_SetVESAPalette; + + if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER) + { + // add linear bit to mode for linear modes + vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE; + vesa_extra[nummodes].pages[0] = 0; + vesa_extra[nummodes].pages[1] = modeinfo.pagesize; + vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; + vesa_modes[nummodes].numpages = modeinfo.numpages; + + vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect; + vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect; + + phys_mem_info.address = (int)modeinfo.pptr; + phys_mem_info.size = 0x400000; + + if (__dpmi_physical_address_mapping(&phys_mem_info)) + goto NextMode; + + vesa_extra[nummodes].plinearmem = + real2ptr (phys_mem_info.address); + } + else + { + // banked at 0xA0000 + vesa_extra[nummodes].vesamode = modeinfo.modenum; + vesa_extra[nummodes].pages[0] = 0; + vesa_extra[nummodes].plinearmem = + real2ptr(modeinfo.winasegment<<4); + + vesa_modes[nummodes].begindirectrect = + VGA_BankedBeginDirectRect; + vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect; + vesa_extra[nummodes].pages[1] = modeinfo.pagesize; + vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; + vesa_modes[nummodes].numpages = modeinfo.numpages; + } + + vesa_extra[nummodes].vga_incompatible = + modeinfo.mode_attributes & VGA_INCOMPATIBLE; + + nummodes++; + } +NextMode: + pmodenums++; + } + +// add the VESA modes at the start of the mode list (if there are any) + if (nummodes) + { + vesa_modes[nummodes-1].pnext = pvidmodes; + pvidmodes = &vesa_modes[0]; + numvidmodes += nummodes; + ppal = dos_getmemory(256*4); + } + + dos_freememory(pinfoblock); +} + + +/* +================ +VID_ExtraGetModeInfo +================ +*/ +qboolean VID_ExtraGetModeInfo(int modenum) +{ + char *infobuf; + int numimagepages; + + infobuf = dos_getmemory(256); + + regs.x.ax = 0x4f01; + regs.x.cx = modenum; + regs.x.es = ptr2real(infobuf) >> 4; + regs.x.di = ptr2real(infobuf) & 0xf; + dos_int86(0x10); + if (regs.x.ax != 0x4f) + { + return false; + } + else + { + modeinfo.modenum = modenum; + modeinfo.bits_per_pixel = *(char*)(infobuf+25); + modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; + modeinfo.width = *(short*)(infobuf+18); + modeinfo.height = *(short*)(infobuf+20); + + // we do only 8-bpp in software + if ((modeinfo.bits_per_pixel != 8) || + (modeinfo.bytes_per_pixel != 1) || + (modeinfo.width > MAXWIDTH) || + (modeinfo.height > MAXHEIGHT)) + { + return false; + } + + modeinfo.mode_attributes = *(short*)infobuf; + + // we only want color graphics modes that are supported by the hardware + if ((modeinfo.mode_attributes & + (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) != + (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) + { + return false; + } + + // we only work with linear frame buffers, except for 320x200, which can + // effectively be linear when banked at 0xA000 + if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)) + { + if ((modeinfo.width != 320) || (modeinfo.height != 200)) + return false; + } + + modeinfo.bytes_per_scanline = *(short*)(infobuf+16); + + modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height; + + if (modeinfo.pagesize > totalvidmem) + return false; + + // force to one page if the adapter reports it doesn't support more pages + // than that, no matter how much memory it has--it may not have hardware + // support for page flipping + numimagepages = *(unsigned char *)(infobuf+29); + + if (numimagepages <= 0) + { + // wrong, but there seems to be an ATI VESA driver that reports 0 + modeinfo.numpages = 1; + } + else if (numimagepages < 3) + { + modeinfo.numpages = numimagepages; + } + else + { + modeinfo.numpages = 3; + } + + if (*(char*)(infobuf+2) & 5) + { + modeinfo.winasegment = *(unsigned short*)(infobuf+8); + modeinfo.win = 0; + } + else if (*(char*)(infobuf+3) & 5) + { + modeinfo.winbsegment = *(unsigned short*)(infobuf+8); + modeinfo.win = 1; + } + modeinfo.granularity = *(short*)(infobuf+4) * 1024; + modeinfo.win_size = *(short*)(infobuf+6) * 1024; + modeinfo.bits_per_pixel = *(char*)(infobuf+25); + modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; + modeinfo.memory_model = *(unsigned char*)(infobuf+27); + modeinfo.num_pages = *(char*)(infobuf+29) + 1; + + modeinfo.red_width = *(char*)(infobuf+31); + modeinfo.red_pos = *(char*)(infobuf+32); + modeinfo.green_width = *(char*)(infobuf+33); + modeinfo.green_pos = *(char*)(infobuf+34); + modeinfo.blue_width = *(char*)(infobuf+35); + modeinfo.blue_pos = *(char*)(infobuf+36); + + modeinfo.pptr = *(long *)(infobuf+40); + +#if 0 + printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum); + printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes); + printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2)); + printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3)); + printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment); + printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment); + printf(" bytes per scanline = %d\n", + modeinfo.bytes_per_scanline); + printf(" width = %d, height = %d\n", modeinfo.width, + modeinfo.height); + printf(" win = %c\n", 'A' + modeinfo.win); + printf(" win granularity = %d\n", modeinfo.granularity); + printf(" win size = %d\n", modeinfo.win_size); + printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel); + printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel); + printf(" memory model = 0x%x\n", modeinfo.memory_model); + printf(" num pages = %d\n", modeinfo.num_pages); + printf(" red width = %d\n", modeinfo.red_width); + printf(" red pos = %d\n", modeinfo.red_pos); + printf(" green width = %d\n", modeinfo.green_width); + printf(" green pos = %d\n", modeinfo.green_pos); + printf(" blue width = %d\n", modeinfo.blue_width); + printf(" blue pos = %d\n", modeinfo.blue_pos); + printf(" phys mem = %x\n", modeinfo.pptr); +#endif + } + + dos_freememory(infobuf); + + return true; +} + + +/* +================ +VID_ExtraInitMode +================ +*/ +int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode) +{ + vesa_extra_t *pextra; + int pageoffset; + + pextra = pcurrentmode->pextradata; + + if (vid_nopageflip.value) + lvid->numpages = 1; + else + lvid->numpages = pcurrentmode->numpages; + +// clean up any old vid buffer lying around, alloc new if needed + if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1)) + return -1; // memory alloc failed + +// clear the screen and wait for the next frame. VGA_pcurmode, which +// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is +// always the first mode set in a session + if (VGA_pcurmode) + VGA_ClearVideoMem (VGA_pcurmode->planar); + +// set the mode + regs.x.ax = 0x4f02; + regs.x.bx = pextra->vesamode; + dos_int86(0x10); + + if (regs.x.ax != 0x4f) + return 0; + + VID_banked = !(pextra->vesamode & LINEAR_MODE); + VID_membase = pextra->plinearmem; + VGA_width = lvid->width; + VGA_height = lvid->height; + VGA_rowbytes = lvid->rowbytes; + + lvid->colormap = host_colormap; + + VID_pagelist = &pextra->pages[0]; + +// wait for display enable by default only when triple-buffering on a VGA- +// compatible machine that actually has a functioning display enable status + vsync_exists = VID_ExtraStateFound (0x08); + de_exists = VID_ExtraStateFound (0x01); + + if (!pextra->vga_incompatible && + (lvid->numpages == 3) && + de_exists && + (_vid_wait_override.value == 0.0)) + { + Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE); + + VID_displayedpage = 0; + VID_currentpage = 1; + } + else + { + if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0)) + { + Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); + VID_displayedpage = VID_currentpage = 0; + } + else + { + Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); + + VID_displayedpage = 0; + + if (lvid->numpages > 1) + VID_currentpage = 1; + else + VID_currentpage = 0; + } + } + +// TODO: really should be a call to a function + pageoffset = VID_pagelist[VID_displayedpage]; + + regs.x.ax = 0x4f07; + regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible + regs.x.cx = pageoffset % VGA_rowbytes; + regs.x.dx = pageoffset / VGA_rowbytes; + dos_int86(0x10); + + if (VID_banked) + { + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86(0x10); + + VGA_pagebase = VID_membase; + } + else + { + VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage]; + } + + if (lvid->numpages > 1) + { + lvid->buffer = VGA_pagebase; + lvid->conbuffer = lvid->buffer; + } + else + { + lvid->rowbytes = lvid->width; + } + + lvid->direct = VGA_pagebase; + lvid->conrowbytes = lvid->rowbytes; + lvid->conwidth = lvid->width; + lvid->conheight = lvid->height; + + lvid->maxwarpwidth = WARP_WIDTH; + lvid->maxwarpheight = WARP_HEIGHT; + + VGA_pcurmode = pcurrentmode; + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + return 1; +} + + +/* +================ +VID_ExtraSwapBuffers +================ +*/ +void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, + vrect_t *rects) +{ + int pageoffset; + + UNUSED(rects); + UNUSED(pcurrentmode); + + pageoffset = VID_pagelist[VID_currentpage]; + +// display the newly finished page + if (lvid->numpages > 1) + { + // page flipped + regs.x.ax = 0x4f07; + + if (vid_wait.value != VID_WAIT_VSYNC) + { + if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists) + VID_ExtraWaitDisplayEnable (); + + regs.x.bx = VESA_DONT_WAIT_VSYNC; + } + else + { + regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait + } + + regs.x.cx = pageoffset % VGA_rowbytes; + regs.x.dx = pageoffset / VGA_rowbytes; + dos_int86(0x10); + + VID_displayedpage = VID_currentpage; + if (++VID_currentpage >= lvid->numpages) + VID_currentpage = 0; + + // + // set the new write window if this is a banked mode; otherwise, set the + // new address to which to write + // + if (VID_banked) + { + regs.x.ax = 0x4f05; + regs.x.bx = 0; + regs.x.dx = VID_currentpage; + dos_int86(0x10); + } + else + { + lvid->direct = lvid->buffer; // direct drawing goes to the + // currently displayed page + lvid->buffer = VID_membase + VID_pagelist[VID_currentpage]; + lvid->conbuffer = lvid->buffer; + } + + VGA_pagebase = lvid->buffer; + } + else + { + // non-page-flipped + if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC)) + { + VGA_WaitVsync (); + } + + while (rects) + { + VGA_UpdateLinearScreen ( + lvid->buffer + rects->x + (rects->y * lvid->rowbytes), + VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), + rects->width, + rects->height, + lvid->rowbytes, + VGA_rowbytes); + + rects = rects->pnext; + } + } +} + diff --git a/WinQuake/vid_null.c b/WinQuake/vid_null.c index 225691b..0571492 100644 --- a/WinQuake/vid_null.c +++ b/WinQuake/vid_null.c @@ -1,87 +1,87 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// vid_null.c -- null video driver to aid porting efforts - -#include "quakedef.h" -#include "d_local.h" - -viddef_t vid; // global video state - -#define BASEWIDTH 320 -#define BASEHEIGHT 200 - -byte vid_buffer[BASEWIDTH*BASEHEIGHT]; -short zbuffer[BASEWIDTH*BASEHEIGHT]; -byte surfcache[256*1024]; - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; - -void VID_SetPalette (unsigned char *palette) -{ -} - -void VID_ShiftPalette (unsigned char *palette) -{ -} - -void VID_Init (unsigned char *palette) -{ - vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH; - vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT; - vid.aspect = 1.0; - vid.numpages = 1; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - vid.buffer = vid.conbuffer = vid_buffer; - vid.rowbytes = vid.conrowbytes = BASEWIDTH; - - d_pzbuffer = zbuffer; - D_InitCaches (surfcache, sizeof(surfcache)); -} - -void VID_Shutdown (void) -{ -} - -void VID_Update (vrect_t *rects) -{ -} - -/* -================ -D_BeginDirectRect -================ -*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ -} - - -/* -================ -D_EndDirectRect -================ -*/ -void D_EndDirectRect (int x, int y, int width, int height) -{ -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// vid_null.c -- null video driver to aid porting efforts + +#include "quakedef.h" +#include "d_local.h" + +viddef_t vid; // global video state + +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +byte vid_buffer[BASEWIDTH*BASEHEIGHT]; +short zbuffer[BASEWIDTH*BASEHEIGHT]; +byte surfcache[256*1024]; + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; + +void VID_SetPalette (unsigned char *palette) +{ +} + +void VID_ShiftPalette (unsigned char *palette) +{ +} + +void VID_Init (unsigned char *palette) +{ + vid.maxwarpwidth = vid.width = vid.conwidth = BASEWIDTH; + vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT; + vid.aspect = 1.0; + vid.numpages = 1; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + vid.buffer = vid.conbuffer = vid_buffer; + vid.rowbytes = vid.conrowbytes = BASEWIDTH; + + d_pzbuffer = zbuffer; + D_InitCaches (surfcache, sizeof(surfcache)); +} + +void VID_Shutdown (void) +{ +} + +void VID_Update (vrect_t *rects) +{ +} + +/* +================ +D_BeginDirectRect +================ +*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + + +/* +================ +D_EndDirectRect +================ +*/ +void D_EndDirectRect (int x, int y, int width, int height) +{ +} + + diff --git a/WinQuake/vid_sunx.c b/WinQuake/vid_sunx.c index 4e27c8d..c398688 100644 --- a/WinQuake/vid_sunx.c +++ b/WinQuake/vid_sunx.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // vid_x.c -- general x video driver #define _BSD diff --git a/WinQuake/vid_sunxil.c b/WinQuake/vid_sunxil.c index 31f301e..368b052 100644 --- a/WinQuake/vid_sunxil.c +++ b/WinQuake/vid_sunxil.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // vid_sunxil.c -- uses X to setup windows and XIL to copy images (scaled as needed) // to screen diff --git a/WinQuake/vid_svgalib.c b/WinQuake/vid_svgalib.c index e0fea3a..2ba0de7 100644 --- a/WinQuake/vid_svgalib.c +++ b/WinQuake/vid_svgalib.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ #include #include #include diff --git a/WinQuake/vid_vga.c b/WinQuake/vid_vga.c index 6fbec9d..47c0084 100644 --- a/WinQuake/vid_vga.c +++ b/WinQuake/vid_vga.c @@ -1,478 +1,478 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// vid_vga.c: VGA-specific DOS video stuff -// - -// TODO: proper handling of page-swap failure - -#include - -#include "quakedef.h" -#include "d_local.h" -#include "dosisms.h" -#include "vid_dos.h" -#include - -extern regs_t regs; - -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; -byte *VGA_pagebase; -vmode_t *VGA_pcurmode; - -static int VGA_planar; -static int VGA_numpages; -static int VGA_buffersize; - -void *vid_surfcache; -int vid_surfcachesize; - -int VGA_highhunkmark; - -#include "vgamodes.h" - -#define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0])) - -void VGA_UpdatePlanarScreen (void *srcbuffer); - -static byte backingbuf[48*24]; - -/* -================ -VGA_BeginDirectRect -================ -*/ -void VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, - int y, byte *pbitmap, int width, int height) -{ - int i, j, k, plane, reps, repshift; - - if (!lvid->direct) - return; - - if (lvid->aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (pcurrentmode->planar) - { - for (plane=0 ; plane<4 ; plane++) - { - // select the correct plane for reading and writing - outportb (SC_INDEX, MAP_MASK); - outportb (SC_DATA, 1 << plane); - outportb (GC_INDEX, READ_MAP); - outportb (GC_DATA, plane); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (k=0 ; k> 2) ; j++) - { - backingbuf[(i + k) * 24 + (j << 2) + plane] = - lvid->direct[(y + i + k) * VGA_rowbytes + - (x >> 2) + j]; - lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = - pbitmap[(i >> repshift) * 24 + - (j << 2) + plane]; - } - } - } - } - } - else - { - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jdirect + x + ((y << repshift) + i + j) * - VGA_rowbytes, - width); - memcpy (lvid->direct + x + ((y << repshift) + i + j) * - VGA_rowbytes, - &pbitmap[(i >> repshift) * width], - width); - } - } - } -} - - -/* -================ -VGA_EndDirectRect -================ -*/ -void VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, - int y, int width, int height) -{ - int i, j, k, plane, reps, repshift; - - if (!lvid->direct) - return; - - if (lvid->aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (pcurrentmode->planar) - { - for (plane=0 ; plane<4 ; plane++) - { - // select the correct plane for writing - outportb (SC_INDEX, MAP_MASK); - outportb (SC_DATA, 1 << plane); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (k=0 ; k> 2) ; j++) - { - lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = - backingbuf[(i + k) * 24 + (j << 2) + plane]; - } - } - } - } - } - else - { - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jdirect + x + ((y << repshift) + i + j) * - VGA_rowbytes, - &backingbuf[(i + j) * 24], - width); - } - } - } -} - - -/* -================ -VGA_Init -================ -*/ -void VGA_Init (void) -{ - int i; - -// link together all the VGA modes - for (i=0 ; i<(NUMVIDMODES - 1) ; i++) - { - vgavidmodes[i].pnext = &vgavidmodes[i+1]; - } - -// add the VGA modes at the start of the mode list - vgavidmodes[NUMVIDMODES-1].pnext = pvidmodes; - pvidmodes = &vgavidmodes[0]; - - numvidmodes += NUMVIDMODES; -} - - -/* -================ -VGA_WaitVsync -================ -*/ -void VGA_WaitVsync (void) -{ - while ((inportb (0x3DA) & 0x08) == 0) - ; -} - - -/* -================ -VGA_ClearVideoMem -================ -*/ -void VGA_ClearVideoMem (int planar) -{ - - if (planar) - { - // enable all planes for writing - outportb (SC_INDEX, MAP_MASK); - outportb (SC_DATA, 0x0F); - } - - Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height); -} - -/* -================ -VGA_FreeAndAllocVidbuffer -================ -*/ -qboolean VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer) -{ - int tsize, tbuffersize; - - if (allocnewbuffer) - { - // alloc an extra line in case we want to wrap, and allocate the z-buffer - tbuffersize = (lvid->rowbytes * (lvid->height + 1)) + - (lvid->width * lvid->height * sizeof (*d_pzbuffer)); - } - else - { - // just allocate the z-buffer - tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer); - } - - tsize = D_SurfaceCacheForRes (lvid->width, lvid->height); - - tbuffersize += tsize; - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - Con_Printf ("Not enough memory for video mode\n"); - VGA_pcurmode = NULL; // so no further accesses to the buffer are - // attempted, particularly when clearing - return false; // not enough memory for mode - } - - VGA_buffersize = tbuffersize; - vid_surfcachesize = tsize; - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (VGA_highhunkmark); - d_pzbuffer = NULL; - } - - VGA_highhunkmark = Hunk_HighMark (); - - d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video"); - - vid_surfcache = (byte *)d_pzbuffer - + lvid->width * lvid->height * sizeof (*d_pzbuffer); - - if (allocnewbuffer) - { - lvid->buffer = (void *)( (byte *)vid_surfcache + vid_surfcachesize); - lvid->conbuffer = lvid->buffer; - } - - return true; -} - - -/* -================ -VGA_CheckAdequateMem -================ -*/ -qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes, - int allocnewbuffer) -{ - int tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - if (allocnewbuffer) - { - // alloc an extra line in case we want to wrap, and allocate the z-buffer - tbuffersize += (rowbytes * (height + 1)); - } - - tbuffersize += D_SurfaceCacheForRes (width, height); - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - return false; // not enough memory for mode - } - - return true; -} - - -/* -================ -VGA_InitMode -================ -*/ -int VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode) -{ - vextra_t *pextra; - - pextra = pcurrentmode->pextradata; - - if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer)) - return -1; // memory alloc failed - - if (VGA_pcurmode) - VGA_ClearVideoMem (VGA_pcurmode->planar); - -// mode 0x13 is the base for all the Mode X-class mode sets - regs.h.ah = 0; - regs.h.al = 0x13; - dos_int86(0x10); - - VGA_pagebase = (void *)real2ptr(0xa0000); - lvid->direct = (pixel_t *)VGA_pagebase; - -// set additional registers as needed - VideoRegisterSet (pextra->pregset); - - VGA_numpages = 1; - lvid->numpages = VGA_numpages; - - VGA_width = (lvid->width + 0x1F) & ~0x1F; - VGA_height = lvid->height; - VGA_planar = pcurrentmode->planar; - if (VGA_planar) - VGA_rowbytes = lvid->rowbytes / 4; - else - VGA_rowbytes = lvid->rowbytes; - VGA_bufferrowbytes = lvid->rowbytes; - lvid->colormap = host_colormap; - lvid->fullbright = 256 - LittleLong (*((int *)lvid->colormap + 2048)); - - lvid->maxwarpwidth = WARP_WIDTH; - lvid->maxwarpheight = WARP_HEIGHT; - - lvid->conbuffer = lvid->buffer; - lvid->conrowbytes = lvid->rowbytes; - lvid->conwidth = lvid->width; - lvid->conheight = lvid->height; - - VGA_pcurmode = pcurrentmode; - - VGA_ClearVideoMem (pcurrentmode->planar); - - if (_vid_wait_override.value) - { - Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); - } - else - { - Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); - } - - D_InitCaches (vid_surfcache, vid_surfcachesize); - - return 1; -} - - -/* -================ -VGA_SetPalette -================ -*/ -void VGA_SetPalette(viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal) -{ - int shiftcomponents=2; - int i; - - UNUSED(lvid); - UNUSED(pcurrentmode); - - dos_outportb(0x3c8, 0); - for (i=0 ; i<768 ; i++) - outportb(0x3c9, pal[i]>>shiftcomponents); -} - - -/* -================ -VGA_SwapBuffersCopy -================ -*/ -void VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t *pcurrentmode, - vrect_t *rects) -{ - - UNUSED(pcurrentmode); - -// TODO: can write a dword at a time -// TODO: put in ASM -// TODO: copy only specified rectangles - if (VGA_planar) - { - - // TODO: copy only specified rectangles - - VGA_UpdatePlanarScreen (lvid->buffer); - } - else - { - while (rects) - { - VGA_UpdateLinearScreen ( - lvid->buffer + rects->x + (rects->y * lvid->rowbytes), - VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), - rects->width, - rects->height, - lvid->rowbytes, - VGA_rowbytes); - - rects = rects->pnext; - } - } -} - - -/* -================ -VGA_SwapBuffers -================ -*/ -void VGA_SwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, vrect_t *rects) -{ - UNUSED(lvid); - - if (vid_wait.value == VID_WAIT_VSYNC) - VGA_WaitVsync (); - - VGA_SwapBuffersCopy (lvid, pcurrentmode, rects); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// vid_vga.c: VGA-specific DOS video stuff +// + +// TODO: proper handling of page-swap failure + +#include + +#include "quakedef.h" +#include "d_local.h" +#include "dosisms.h" +#include "vid_dos.h" +#include + +extern regs_t regs; + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; +byte *VGA_pagebase; +vmode_t *VGA_pcurmode; + +static int VGA_planar; +static int VGA_numpages; +static int VGA_buffersize; + +void *vid_surfcache; +int vid_surfcachesize; + +int VGA_highhunkmark; + +#include "vgamodes.h" + +#define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0])) + +void VGA_UpdatePlanarScreen (void *srcbuffer); + +static byte backingbuf[48*24]; + +/* +================ +VGA_BeginDirectRect +================ +*/ +void VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, + int y, byte *pbitmap, int width, int height) +{ + int i, j, k, plane, reps, repshift; + + if (!lvid->direct) + return; + + if (lvid->aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (pcurrentmode->planar) + { + for (plane=0 ; plane<4 ; plane++) + { + // select the correct plane for reading and writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 1 << plane); + outportb (GC_INDEX, READ_MAP); + outportb (GC_DATA, plane); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (k=0 ; k> 2) ; j++) + { + backingbuf[(i + k) * 24 + (j << 2) + plane] = + lvid->direct[(y + i + k) * VGA_rowbytes + + (x >> 2) + j]; + lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = + pbitmap[(i >> repshift) * 24 + + (j << 2) + plane]; + } + } + } + } + } + else + { + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jdirect + x + ((y << repshift) + i + j) * + VGA_rowbytes, + width); + memcpy (lvid->direct + x + ((y << repshift) + i + j) * + VGA_rowbytes, + &pbitmap[(i >> repshift) * width], + width); + } + } + } +} + + +/* +================ +VGA_EndDirectRect +================ +*/ +void VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, + int y, int width, int height) +{ + int i, j, k, plane, reps, repshift; + + if (!lvid->direct) + return; + + if (lvid->aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (pcurrentmode->planar) + { + for (plane=0 ; plane<4 ; plane++) + { + // select the correct plane for writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 1 << plane); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (k=0 ; k> 2) ; j++) + { + lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = + backingbuf[(i + k) * 24 + (j << 2) + plane]; + } + } + } + } + } + else + { + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jdirect + x + ((y << repshift) + i + j) * + VGA_rowbytes, + &backingbuf[(i + j) * 24], + width); + } + } + } +} + + +/* +================ +VGA_Init +================ +*/ +void VGA_Init (void) +{ + int i; + +// link together all the VGA modes + for (i=0 ; i<(NUMVIDMODES - 1) ; i++) + { + vgavidmodes[i].pnext = &vgavidmodes[i+1]; + } + +// add the VGA modes at the start of the mode list + vgavidmodes[NUMVIDMODES-1].pnext = pvidmodes; + pvidmodes = &vgavidmodes[0]; + + numvidmodes += NUMVIDMODES; +} + + +/* +================ +VGA_WaitVsync +================ +*/ +void VGA_WaitVsync (void) +{ + while ((inportb (0x3DA) & 0x08) == 0) + ; +} + + +/* +================ +VGA_ClearVideoMem +================ +*/ +void VGA_ClearVideoMem (int planar) +{ + + if (planar) + { + // enable all planes for writing + outportb (SC_INDEX, MAP_MASK); + outportb (SC_DATA, 0x0F); + } + + Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height); +} + +/* +================ +VGA_FreeAndAllocVidbuffer +================ +*/ +qboolean VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer) +{ + int tsize, tbuffersize; + + if (allocnewbuffer) + { + // alloc an extra line in case we want to wrap, and allocate the z-buffer + tbuffersize = (lvid->rowbytes * (lvid->height + 1)) + + (lvid->width * lvid->height * sizeof (*d_pzbuffer)); + } + else + { + // just allocate the z-buffer + tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer); + } + + tsize = D_SurfaceCacheForRes (lvid->width, lvid->height); + + tbuffersize += tsize; + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < minimum_memory) + { + Con_Printf ("Not enough memory for video mode\n"); + VGA_pcurmode = NULL; // so no further accesses to the buffer are + // attempted, particularly when clearing + return false; // not enough memory for mode + } + + VGA_buffersize = tbuffersize; + vid_surfcachesize = tsize; + + if (d_pzbuffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (VGA_highhunkmark); + d_pzbuffer = NULL; + } + + VGA_highhunkmark = Hunk_HighMark (); + + d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video"); + + vid_surfcache = (byte *)d_pzbuffer + + lvid->width * lvid->height * sizeof (*d_pzbuffer); + + if (allocnewbuffer) + { + lvid->buffer = (void *)( (byte *)vid_surfcache + vid_surfcachesize); + lvid->conbuffer = lvid->buffer; + } + + return true; +} + + +/* +================ +VGA_CheckAdequateMem +================ +*/ +qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes, + int allocnewbuffer) +{ + int tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + if (allocnewbuffer) + { + // alloc an extra line in case we want to wrap, and allocate the z-buffer + tbuffersize += (rowbytes * (height + 1)); + } + + tbuffersize += D_SurfaceCacheForRes (width, height); + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < minimum_memory) + { + return false; // not enough memory for mode + } + + return true; +} + + +/* +================ +VGA_InitMode +================ +*/ +int VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode) +{ + vextra_t *pextra; + + pextra = pcurrentmode->pextradata; + + if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer)) + return -1; // memory alloc failed + + if (VGA_pcurmode) + VGA_ClearVideoMem (VGA_pcurmode->planar); + +// mode 0x13 is the base for all the Mode X-class mode sets + regs.h.ah = 0; + regs.h.al = 0x13; + dos_int86(0x10); + + VGA_pagebase = (void *)real2ptr(0xa0000); + lvid->direct = (pixel_t *)VGA_pagebase; + +// set additional registers as needed + VideoRegisterSet (pextra->pregset); + + VGA_numpages = 1; + lvid->numpages = VGA_numpages; + + VGA_width = (lvid->width + 0x1F) & ~0x1F; + VGA_height = lvid->height; + VGA_planar = pcurrentmode->planar; + if (VGA_planar) + VGA_rowbytes = lvid->rowbytes / 4; + else + VGA_rowbytes = lvid->rowbytes; + VGA_bufferrowbytes = lvid->rowbytes; + lvid->colormap = host_colormap; + lvid->fullbright = 256 - LittleLong (*((int *)lvid->colormap + 2048)); + + lvid->maxwarpwidth = WARP_WIDTH; + lvid->maxwarpheight = WARP_HEIGHT; + + lvid->conbuffer = lvid->buffer; + lvid->conrowbytes = lvid->rowbytes; + lvid->conwidth = lvid->width; + lvid->conheight = lvid->height; + + VGA_pcurmode = pcurrentmode; + + VGA_ClearVideoMem (pcurrentmode->planar); + + if (_vid_wait_override.value) + { + Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); + } + else + { + Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); + } + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + return 1; +} + + +/* +================ +VGA_SetPalette +================ +*/ +void VGA_SetPalette(viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal) +{ + int shiftcomponents=2; + int i; + + UNUSED(lvid); + UNUSED(pcurrentmode); + + dos_outportb(0x3c8, 0); + for (i=0 ; i<768 ; i++) + outportb(0x3c9, pal[i]>>shiftcomponents); +} + + +/* +================ +VGA_SwapBuffersCopy +================ +*/ +void VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t *pcurrentmode, + vrect_t *rects) +{ + + UNUSED(pcurrentmode); + +// TODO: can write a dword at a time +// TODO: put in ASM +// TODO: copy only specified rectangles + if (VGA_planar) + { + + // TODO: copy only specified rectangles + + VGA_UpdatePlanarScreen (lvid->buffer); + } + else + { + while (rects) + { + VGA_UpdateLinearScreen ( + lvid->buffer + rects->x + (rects->y * lvid->rowbytes), + VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), + rects->width, + rects->height, + lvid->rowbytes, + VGA_rowbytes); + + rects = rects->pnext; + } + } +} + + +/* +================ +VGA_SwapBuffers +================ +*/ +void VGA_SwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, vrect_t *rects) +{ + UNUSED(lvid); + + if (vid_wait.value == VID_WAIT_VSYNC) + VGA_WaitVsync (); + + VGA_SwapBuffersCopy (lvid, pcurrentmode, rects); +} + diff --git a/WinQuake/vid_win.c b/WinQuake/vid_win.c index db90689..6347669 100644 --- a/WinQuake/vid_win.c +++ b/WinQuake/vid_win.c @@ -1,3343 +1,3343 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// vid_win.c -- Win32 video driver - -#include "quakedef.h" -#include "winquake.h" -#include "d_local.h" -#include "resource.h" - -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 - -qboolean dibonly; - -extern int Minimized; - -HWND mainwindow; - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -int DIBWidth, DIBHeight; -qboolean DDActive; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -RECT window_rect; - -static DEVMODE gdevmode; -static qboolean startwindowed = 0, windowed_mode_set; -static int firstupdate = 1; -static qboolean vid_initialized = false, vid_palettized; -static int lockcount; -static int vid_fulldib_on_focus_mode; -static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; -static int vid_stretched, windowed_mouse; -static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; -static HICON hIcon; - -viddef_t vid; // global video state - -#define MODE_WINDOWED 0 -#define MODE_SETTABLE_WINDOW 2 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) - -// Note that 0 is MODE_WINDOWED -cvar_t vid_mode = {"vid_mode","0", false}; -// Note that 0 is MODE_WINDOWED -cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; -// Note that 3 is MODE_FULLSCREEN_DEFAULT -cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; -cvar_t vid_wait = {"vid_wait","0"}; -cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; -cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; -cvar_t vid_config_x = {"vid_config_x","800", true}; -cvar_t vid_config_y = {"vid_config_y","600", true}; -cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; -cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; -cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; -cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; -cvar_t block_switch = {"block_switch","0", true}; -cvar_t vid_window_x = {"vid_window_x", "0", true}; -cvar_t vid_window_y = {"vid_window_y", "0", true}; - -typedef struct { - int width; - int height; -} lmode_t; - -lmode_t lowresmodes[] = { - {320, 200}, - {320, 240}, - {400, 300}, - {512, 384}, -}; - -int vid_modenum = NO_MODE; -int vid_testingmode, vid_realmode; -double vid_testendtime; -int vid_default = MODE_WINDOWED; -static int windowed_default; - -modestate_t modestate = MS_UNINIT; - -static byte *vid_surfcache; -static int vid_surfcachesize; -static int VID_highhunkmark; - -unsigned char vid_curpal[256*3]; - -unsigned short d_8to16table[256]; -unsigned d_8to24table[256]; - -int driver = grDETECT,mode; -bool useWinDirect = true, useDirectDraw = true; -MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int mode13; - int stretched; - int dib; - int fullscreen; - int bpp; - int halfscreen; - char modedesc[13]; -} vmode_t; - -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; -static vmode_t *pcurrentmode; - -int aPage; // Current active display page -int vPage; // Current visible display page -int waitVRT = true; // True to wait for retrace on flip - -static vmode_t badmode; - -static byte backingbuf[48*24]; - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate(BOOL fActive, BOOL minimize); - - -/* -================ -VID_RememberWindowPos -================ -*/ -void VID_RememberWindowPos (void) -{ - RECT rect; - - if (GetWindowRect (mainwindow, &rect)) - { - if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && - (rect.top < GetSystemMetrics (SM_CYSCREEN)) && - (rect.right > 0) && - (rect.bottom > 0)) - { - Cvar_SetValue ("vid_window_x", (float)rect.left); - Cvar_SetValue ("vid_window_y", (float)rect.top); - } - } -} - - -/* -================ -VID_CheckWindowXY -================ -*/ -void VID_CheckWindowXY (void) -{ - - if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - ((int)vid_window_x.value < 0) || - ((int)vid_window_y.value < 0)) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0 ); - } -} - - -/* -================ -VID_UpdateWindowStatus -================ -*/ -void VID_UpdateWindowStatus (void) -{ - - window_rect.left = window_x; - window_rect.top = window_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; - - IN_UpdateClipCursor (); -} - - -/* -================ -ClearAllStates -================ -*/ -void ClearAllStates (void) -{ - int i; - -// send an up event for each key, to make sure the server clears them all - for (i=0 ; i<256 ; i++) - { - Key_Event (i, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - - -/* -================ -VID_CheckAdequateMem -================ -*/ -qboolean VID_CheckAdequateMem (int width, int height) -{ - int tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tbuffersize += D_SurfaceCacheForRes (width, height); - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - return false; // not enough memory for mode - } - - return true; -} - - -/* -================ -VID_AllocBuffers -================ -*/ -qboolean VID_AllocBuffers (int width, int height) -{ - int tsize, tbuffersize; - - tbuffersize = width * height * sizeof (*d_pzbuffer); - - tsize = D_SurfaceCacheForRes (width, height); - - tbuffersize += tsize; - -// see if there's enough memory, allowing for the normal mode 0x13 pixel, -// z, and surface buffers - if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + - 0x10000 * 3) < minimum_memory) - { - Con_SafePrintf ("Not enough memory for video mode\n"); - return false; // not enough memory for mode - } - - vid_surfcachesize = tsize; - - if (d_pzbuffer) - { - D_FlushCaches (); - Hunk_FreeToHighMark (VID_highhunkmark); - d_pzbuffer = NULL; - } - - VID_highhunkmark = Hunk_HighMark (); - - d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); - - vid_surfcache = (byte *)d_pzbuffer + - width * height * sizeof (*d_pzbuffer); - - return true; -} - - -void initFatalError(void) -{ - MGL_exit(); - MGL_fatalError(MGL_errorMsg(MGL_result())); - exit(EXIT_FAILURE); -} - - -int VID_Suspend (MGLDC *dc,m_int flags) -{ - - if (flags & MGL_DEACTIVATE) - { - // FIXME: this doesn't currently work on NT - if (block_switch.value && !WinNT) - { - return MGL_NO_DEACTIVATE; - } - - S_BlockSound (); - S_ClearBuffer (); - - IN_RestoreOriginalMouseState (); - CDAudio_Pause (); - - // keep WM_PAINT from trying to redraw - in_mode_set = true; - - block_drawing = true; // so we don't try to draw while switched away - - return MGL_NO_SUSPEND_APP; - } - else if (flags & MGL_REACTIVATE) - { - IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - CDAudio_Resume (); - S_UnblockSound (); - - in_mode_set = false; - - vid.recalc_refdef = 1; - - block_drawing = false; - - return MGL_NO_SUSPEND_APP; - } - -} - - -void registerAllDispDrivers(void) -{ - /* Event though these driver require WinDirect, we register - * them so that they will still be available even if DirectDraw - * is present and the user has disable the high performance - * WinDirect modes. - */ - MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); -// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); - - /* Register display drivers */ - if (useWinDirect) - { -//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); - MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); - - if (!COM_CheckParm ("-novbeaf")) - MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); - } - - if (useDirectDraw) - { - MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); - } -} - - -void registerAllMemDrivers(void) -{ - /* Register memory context drivers */ - MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); -} - - -void VID_InitMGLFull (HINSTANCE hInstance) -{ - int i, xRes, yRes, bits, vMode, lowres, curmode, temp; - int lowstretchedres, stretchedmode, lowstretched; - uchar *m; - -// FIXME: NT is checked for because MGL currently has a bug that causes it -// to try to use WinDirect modes even on NT - if (COM_CheckParm("-nowindirect") || - COM_CheckParm("-nowd") || - COM_CheckParm("-novesa") || - WinNT) - { - useWinDirect = false; - } - - if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) - useDirectDraw = false; - - // Initialise the MGL - MGL_unregisterAllDrivers(); - registerAllDispDrivers(); - registerAllMemDrivers(); - MGL_detectGraph(&driver,&mode); - m = MGL_availableModes(); - - if (m[0] != 0xFF) - { - lowres = lowstretchedres = 99999; - lowstretched = 0; - curmode = 0; - - // find the lowest-res mode, or a mode we can stretch up to and get - // lowest-res that way - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (curmode < MAX_MODE_LIST)) - { - if (m[i] == grVGA_320x200x256) - is_mode0x13 = true; - - if (!COM_CheckParm("-noforcevga")) - { - if (m[i] == grVGA_320x200x256) - { - mode = i; - break; - } - } - - if (xRes < lowres) - { - lowres = xRes; - mode = i; - } - - if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) - { - lowstretchedres = xRes >> 1; - stretchedmode = i; - } - } - - curmode++; - } - - // if there's a mode we can stretch by 2 up to, thereby effectively getting - // a lower-res mode than the lowest-res real but still at least 320x200, that - // will be our default mode - if (lowstretchedres < lowres) - { - mode = stretchedmode; - lowres = lowstretchedres; - lowstretched = 1; - } - - // build the mode list, leaving room for the low-res stretched mode, if any - nummodes++; // leave room for default mode - - for (i = 0; m[i] != 0xFF; i++) - { - MGL_modeResolution(m[i], &xRes, &yRes,&bits); - - if ((bits == 8) && - (xRes <= MAXWIDTH) && - (yRes <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - if (i == mode) - { - if (lowstretched) - { - stretchedmode = nummodes; - curmode = nummodes++; - } - else - { - curmode = MODE_FULLSCREEN_DEFAULT; - } - } - else - { - curmode = nummodes++; - } - - modelist[curmode].type = MS_FULLSCREEN; - modelist[curmode].width = xRes; - modelist[curmode].height = yRes; - sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); - - if (m[i] == grVGA_320x200x256) - modelist[curmode].mode13 = 1; - else - modelist[curmode].mode13 = 0; - - modelist[curmode].modenum = m[i]; - modelist[curmode].stretched = 0; - modelist[curmode].dib = 0; - modelist[curmode].fullscreen = 1; - modelist[curmode].halfscreen = 0; - modelist[curmode].bpp = 8; - } - } - - if (lowstretched) - { - modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; - modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; - modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; - modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; - sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", - modelist[MODE_FULLSCREEN_DEFAULT].width, - modelist[MODE_FULLSCREEN_DEFAULT].height); - } - - vid_default = MODE_FULLSCREEN_DEFAULT; - - temp = m[0]; - - if (!MGL_init(&driver, &temp, "")) - { - initFatalError(); - } - } - - MGL_setSuspendAppCallback(VID_Suspend); -} - - -MGLDC *createDisplayDC(int forcemem) -/**************************************************************************** -* -* Function: createDisplayDC -* Returns: Pointer to the MGL device context to use for the application -* -* Description: Initialises the MGL and creates an appropriate display -* device context to be used by the GUI. This creates and -* apropriate device context depending on the system being -* compile for, and should be the only place where system -* specific code is required. -* -****************************************************************************/ -{ - MGLDC *dc; - pixel_format_t pf; - int npages; - - // Start the specified video mode - if (!MGL_changeDisplayMode(mode)) - initFatalError(); - - npages = MGL_availablePages(mode); - - if (npages > 3) - npages = 3; - - if (!COM_CheckParm ("-notriplebuf")) - { - if (npages > 2) - { - npages = 2; - } - } - - if ((dc = MGL_createDisplayDC(npages)) == NULL) - return NULL; - - if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) - { - MGL_makeCurrentDC(dc); - memdc = NULL; - } - else - { - // Set up for blitting from a memory buffer - memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); - MGL_makeCurrentDC(memdc); - } - - // Enable page flipping even for even for blitted surfaces - if (forcemem) - { - vid.numpages = 1; - } - else - { - vid.numpages = dc->mi.maxPage + 1; - - if (vid.numpages > 1) - { - // Set up for page flipping - MGL_setActivePage(dc, aPage = 1); - MGL_setVisualPage(dc, vPage = 0, false); - } - - if (vid.numpages > 3) - vid.numpages = 3; - } - - if (vid.numpages == 2) - waitVRT = true; - else - waitVRT = false; - - return dc; -} - - -void VID_InitMGLDIB (HINSTANCE hInstance) -{ - WNDCLASS wc; - HDC hdc; - int i; - - hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); - - /* Register the frame class */ - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)MainWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = 0; - wc.hCursor = LoadCursor (NULL,IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = 0; - wc.lpszClassName = "WinQuake"; - - if (!RegisterClass (&wc) ) - Sys_Error ("Couldn't register window class"); - - /* Find the size for the DIB window */ - /* Initialise the MGL for windowed operation */ - MGL_setAppInstance(hInstance); - registerAllMemDrivers(); - MGL_initWindowed(""); - - modelist[0].type = MS_WINDOWED; - modelist[0].width = 320; - modelist[0].height = 240; - strcpy (modelist[0].modedesc, "320x240"); - modelist[0].mode13 = 0; - modelist[0].modenum = MODE_WINDOWED; - modelist[0].stretched = 0; - modelist[0].dib = 1; - modelist[0].fullscreen = 0; - modelist[0].halfscreen = 0; - modelist[0].bpp = 8; - - modelist[1].type = MS_WINDOWED; - modelist[1].width = 640; - modelist[1].height = 480; - strcpy (modelist[1].modedesc, "640x480"); - modelist[1].mode13 = 0; - modelist[1].modenum = MODE_WINDOWED + 1; - modelist[1].stretched = 1; - modelist[1].dib = 1; - modelist[1].fullscreen = 0; - modelist[1].halfscreen = 0; - modelist[1].bpp = 8; - - modelist[2].type = MS_WINDOWED; - modelist[2].width = 800; - modelist[2].height = 600; - strcpy (modelist[2].modedesc, "800x600"); - modelist[2].mode13 = 0; - modelist[2].modenum = MODE_WINDOWED + 2; - modelist[2].stretched = 1; - modelist[2].dib = 1; - modelist[2].fullscreen = 0; - modelist[2].halfscreen = 0; - modelist[2].bpp = 8; - -// automatically stretch the default mode up if > 640x480 desktop resolution - hdc = GetDC(NULL); - - if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) - { - vid_default = MODE_WINDOWED + 1; - } - else - { - vid_default = MODE_WINDOWED; - } - - windowed_default = vid_default; - - ReleaseDC(NULL,hdc); - - nummodes = 3; // reserve space for windowed mode - - DDActive = 0; -} - - -/* -================= -VID_InitFullDIB -================= -*/ -void VID_InitFullDIB (HINSTANCE hInstance) -{ - DEVMODE devmode; - int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; - int numlowresmodes, bpp, done; - int cstretch, istretch, mstretch; - BOOL stat; - -// enumerate 8 bpp modes - originalnummodes = nummodes; - modenum = 0; - lowestres = 99999; - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((devmode.dmBitsPerPel == 8) && - (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && - (nummodes < MAX_MODE_LIST)) - { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height << 1)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i 8 bpp - if (nummodes == originalnummodes) - { - modenum = 0; - lowestres = 99999; - - Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); - - do - { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((((devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT)) || - (!COM_CheckParm("-noadjustaspect") && - (devmode.dmPelsWidth <= (MAXWIDTH*2)) && - (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && - (nummodes < MAX_MODE_LIST) && - (devmode.dmBitsPerPel > 8)) - { - devmode.dmFields = DM_BITSPERPEL | - DM_PELSWIDTH | - DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) - { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].mode13 = 0; - modelist[nummodes].stretched = 0; - modelist[nummodes].halfscreen = 0; - modelist[nummodes].dib = 1; - modelist[nummodes].fullscreen = 1; - modelist[nummodes].bpp = devmode.dmBitsPerPel; - sprintf (modelist[nummodes].modedesc, "%dx%d", - devmode.dmPelsWidth, devmode.dmPelsHeight); - - // if the width is more than twice the height, reduce it by half because this - // is probably a dual-screen monitor - if (!COM_CheckParm("-noadjustaspect")) - { - if (modelist[nummodes].width > (modelist[nummodes].height*2)) - { - modelist[nummodes].width >>= 1; - modelist[nummodes].halfscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - modelist[nummodes].width, - modelist[nummodes].height); - } - } - - for (i=originalnummodes, existingmode = 0 ; i= modelist[i].bpp)) - { - existingmode = 1; - break; - } - } - - if (!existingmode) - { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - switch (bpp) - { - case 8: - bpp = 16; - break; - - case 16: - bpp = 32; - break; - - case 32: - done = 1; - break; - } - } - -// now add the lowest stretch-by-2 pseudo-modes between 320-wide -// (inclusive) and lowest real res (not inclusive) -// don't bother if we have a real VGA mode 0x13 mode - if (!is_mode0x13) - { - for (i=originalnummodes, cstretch=0 ; i> 1) < lowestres) && - ((modelist[i].width >> 1) >= 320)) - { - lowestres = modelist[i].width >> 1; - cstretch = 1; - mstretch = i; - } - } - - if ((nummodes + cstretch) > MAX_MODE_LIST) - cstretch = MAX_MODE_LIST - nummodes; - - if (cstretch > 0) - { - for (i=(nummodes-1) ; i>=originalnummodes ; i--) - modelist[i+cstretch] = modelist[i]; - - nummodes += cstretch; - istretch = originalnummodes; - - modelist[istretch] = modelist[mstretch]; - modelist[istretch].width >>= 1; - modelist[istretch].height >>= 1; - modelist[istretch].stretched = 1; - sprintf (modelist[istretch].modedesc, "%dx%d", - modelist[istretch].width, modelist[istretch].height); - } - } - - if (nummodes != originalnummodes) - vid_default = MODE_FULLSCREEN_DEFAULT; - else - Con_SafePrintf ("No fullscreen DIB modes found\n"); -} - - -/* -================= -VID_NumModes -================= -*/ -int VID_NumModes (void) -{ - return nummodes; -} - - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t *VID_GetModePtr (int modenum) -{ - - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; -} - - -/* -================= -VID_CheckModedescFixup -================= -*/ -void VID_CheckModedescFixup (int mode) -{ - int x, y, stretch; - - if (mode == MODE_SETTABLE_WINDOW) - { - modelist[mode].stretched = (int)vid_stretch_by_2.value; - stretch = modelist[mode].stretched; - - if (vid_config_x.value < (320 << stretch)) - vid_config_x.value = 320 << stretch; - - if (vid_config_y.value < (200 << stretch)) - vid_config_y.value = 200 << stretch; - - x = (int)vid_config_x.value; - y = (int)vid_config_y.value; - sprintf (modelist[mode].modedesc, "%dx%d", x, y); - modelist[mode].width = x; - modelist[mode].height = y; - } -} - - -/* -================= -VID_GetModeDescriptionMemCheck -================= -*/ -char *VID_GetModeDescriptionMemCheck (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - - if (VID_CheckAdequateMem (pv->width, pv->height)) - { - return pinfo; - } - else - { - return NULL; - } -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char *VID_GetModeDescription (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - return pinfo; -} - - -/* -================= -VID_GetModeDescription2 - -Tacks on "windowed" or "fullscreen" -================= -*/ -char *VID_GetModeDescription2 (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -// KJB: Added this to return the mode driver name in description for console - -char *VID_GetExtModeDescription (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - - pv = VID_GetModePtr (mode); - if (modelist[mode].type == MS_FULLSCREEN) - { - sprintf(pinfo,"%s fullscreen %s",pv->modedesc, - MGL_modeDriverName(pv->modenum)); - } - else if (modelist[mode].type == MS_FULLDIB) - { - sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); - } - else - { - sprintf(pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -void DestroyDIBWindow (void) -{ - - if (modestate == MS_WINDOWED) - { - // destroy the associated MGL DC's; the window gets reused - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -void DestroyFullscreenWindow (void) -{ - - if (modestate == MS_FULLSCREEN) - { - // destroy the existing fullscreen mode and DC's - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - } -} - - - -void DestroyFullDIBWindow (void) -{ - if (modestate == MS_FULLDIB) - { - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - // Destroy the fullscreen DIB window and associated MGL DC's - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - } -} - - -qboolean VID_SetWindowedMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - qboolean stretched; - int lastmodestate; - LONG wlong; - - if (!windowed_mode_set) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - windowed_mode_set; - } - - VID_CheckModedescFixup (modenum); - - DDActive = 0; - lastmodestate = modestate; - - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - -// KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - stretched = modelist[modenum].stretched; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - if (stretched) - { - DIBWidth >>= 1; - DIBHeight >>= 1; - } - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - -// the first time we're called to set the mode, create the window we'll use -// for the rest of the session - if (!vid_mode_set) - { - mainwindow = CreateWindowEx ( - ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, - NULL, - global_hInstance, - NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window"); - - // tell MGL to use this window for fullscreen modes - MGL_registerFullScreenWindow (mainwindow); - - vid_mode_set = true; - } - else - { - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - } - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER | - SWP_HIDEWINDOW)) - { - Sys_Error ("Couldn't resize DIB window"); - } - - if (hide_window) - return true; - -// position and show the DIB window - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - - if (force_minimized) - ShowWindow (mainwindow, SW_MINIMIZE); - else - ShowWindow (mainwindow, SW_SHOWDEFAULT); - - UpdateWindow (mainwindow); - - modestate = MS_WINDOWED; - vid_fulldib_on_focus_mode = 0; - -// because we have set the background brush for the window to NULL -// (to avoid flickering when re-sizing the window on the desktop), -// we clear the window to black when created, otherwise it will be -// empty while Quake starts up. - hdc = GetDC(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Windowed DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = stretched; - - SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); - - return true; -} - - -qboolean VID_SetFullscreenMode (int modenum) -{ - - DDActive = 1; - - DestroyDIBWindow (); - DestroyFullDIBWindow (); - - mode = modelist[modenum].modenum; - - // Destroy old DC's, resetting back to fullscreen mode - if (mgldc) - MGL_destroyDC (mgldc); - if (memdc) - MGL_destroyDC (memdc); - mgldc = memdc = NULL; - - if ((mgldc = createDisplayDC (modelist[modenum].stretched || - (int)vid_nopageflip.value)) == NULL) - { - return false; - } - - modestate = MS_FULLSCREEN; - vid_fulldib_on_focus_mode = 0; - - vid.buffer = vid.conbuffer = vid.direct = NULL; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - DIBHeight = vid.height = vid.conheight = modelist[modenum].height; - DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - -// set the large icon, so the Quake icon will show up in the taskbar - SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); - -// shouldn't be needed, but Kendall needs to let us get the activation -// message for this not to be needed on NT - AppActivate (true, false); - - return true; -} - - -qboolean VID_SetFullDIBMode (int modenum) -{ - HDC hdc; - pixel_format_t pf; - int lastmodestate; - - DDActive = 0; - - DestroyFullscreenWindow (); - DestroyDIBWindow (); - - if (windc) - MGL_destroyDC(windc); - if (dibdc) - MGL_destroyDC(dibdc); - windc = dibdc = NULL; - -// KJB: Signal to the MGL that we are going back to windowed mode - if (!MGL_changeDisplayMode(grWINDOWED)) - initFatalError(); - - gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - gdevmode.dmBitsPerPel = modelist[modenum].bpp; - gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << - modelist[modenum].halfscreen; - gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; - gdevmode.dmSize = sizeof (gdevmode); - - if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode"); - - lastmodestate = modestate; - modestate = MS_FULLDIB; - vid_fulldib_on_focus_mode = modenum; - - WindowRect.top = WindowRect.left = 0; - - hdc = GetDC(NULL); - - WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; - WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; - - ReleaseDC(NULL,hdc); - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - ExWindowStyle = 0; - AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); - - SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); - - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER)) - { - Sys_Error ("Couldn't resize DIB window"); - } - -// position and show the DIB window - SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - // Because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), we - // clear the window to black when created, otherwise it will be - // empty while Quake starts up. - hdc = GetDC(mainwindow); - PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); - ReleaseDC(mainwindow, hdc); - - /* Create the MGL window DC and the MGL memory DC */ - if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) - MGL_fatalError("Unable to create Fullscreen DIB DC!"); - - if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) - MGL_fatalError("Unable to create Memory DC!"); - - MGL_makeCurrentDC(dibdc); - - vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; - vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; - vid.numpages = 1; - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.height = vid.conheight = DIBHeight; - vid.width = vid.conwidth = DIBWidth; - vid.aspect = ((float)vid.height / (float)vid.width) * - (320.0 / 240.0); - - vid_stretched = modelist[modenum].stretched; - -// needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - return true; -} - - -void VID_RestoreOldMode (int original_mode) -{ - static qboolean inerror = false; - - if (inerror) - return; - - in_mode_set = false; - inerror = true; - -// make sure mode set happens (video mode changes) - vid_modenum = original_mode - 1; - - if (!VID_SetMode (original_mode, vid_curpal)) - { - vid_modenum = MODE_WINDOWED - 1; - - if (!VID_SetMode (windowed_default, vid_curpal)) - Sys_Error ("Can't set any video mode"); - } - - inerror = false; -} - - -void VID_SetDefaultMode (void) -{ - - if (vid_initialized) - VID_SetMode (0, vid_curpal); - - IN_DeactivateMouse (); -} - - -int VID_SetMode (int modenum, unsigned char *palette) -{ - int original_mode, temp, dummy; - qboolean stat; - MSG msg; - HDC hdc; - - while ((modenum >= nummodes) || (modenum < 0)) - { - if (vid_modenum == NO_MODE) - { - if (modenum == vid_default) - { - modenum = windowed_default; - } - else - { - modenum = vid_default; - } - - Cvar_SetValue ("vid_mode", (float)modenum); - } - else - { - Cvar_SetValue ("vid_mode", (float)vid_modenum); - return 0; - } - } - - if (!force_mode_set && (modenum == vid_modenum)) - return true; - -// so Con_Printfs don't mess us up by forcing vid and snd updates - temp = scr_disabled_for_loading; - scr_disabled_for_loading = true; - in_mode_set = true; - - CDAudio_Pause (); - S_ClearBuffer (); - - if (vid_modenum == NO_MODE) - original_mode = windowed_default; - else - original_mode = vid_modenum; - - // Set either the fullscreen or windowed mode - if (modelist[modenum].type == MS_WINDOWED) - { - if (_windowed_mouse.value) - { - stat = VID_SetWindowedMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode(modenum); - } - } - else if (modelist[modenum].type == MS_FULLDIB) - { - stat = VID_SetFullDIBMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - stat = VID_SetFullscreenMode(modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - - window_width = vid.width << vid_stretched; - window_height = vid.height << vid_stretched; - VID_UpdateWindowStatus (); - - CDAudio_Resume (); - scr_disabled_for_loading = temp; - - if (!stat) - { - VID_RestoreOldMode (original_mode); - return false; - } - - if (hide_window) - return true; - -// now we try to make sure we get the focus on the mode switch, because -// sometimes in some systems we don't. We grab the foreground, then -// finish setting up, pump all our messages, and sleep for a little while -// to let messages finish bouncing around the system, then we put -// ourselves at the top of the z order, then grab the foreground again, -// Who knows if it helps, but it probably doesn't hurt - if (!force_minimized) - SetForegroundWindow (mainwindow); - - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - VID_SetPalette (palette); - - ReleaseDC(NULL,hdc); - - vid_modenum = modenum; - Cvar_SetValue ("vid_mode", (float)vid_modenum); - - if (!VID_AllocBuffers (vid.width, vid.height)) - { - // couldn't get memory for this mode; try to fall back to previous mode - VID_RestoreOldMode (original_mode); - return false; - } - - D_InitCaches (vid_surfcache, vid_surfcachesize); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - if (!force_minimized) - { - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (mainwindow); - } - -// fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - if (!msg_suppress_1) - Con_SafePrintf ("%s\n", VID_GetModeDescription (vid_modenum)); - - VID_SetPalette (palette); - - in_mode_set = false; - vid.recalc_refdef = 1; - - return true; -} - -void VID_LockBuffer (void) -{ - - if (dibdc) - return; - - lockcount++; - - if (lockcount > 1) - return; - - MGL_beginDirectAccess(); - - if (memdc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = memdc->surface; - vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; - } - else if (mgldc) - { - // Update surface pointer for linear access modes - vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; - vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; - } - - if (r_dowarp) - d_viewbuffer = r_warpbuffer; - else - d_viewbuffer = (void *)(byte *)vid.buffer; - - if (r_dowarp) - screenwidth = WARP_WIDTH; - else - screenwidth = vid.rowbytes; - - if (lcd_x.value) - screenwidth <<= 1; -} - - -void VID_UnlockBuffer (void) -{ - if (dibdc) - return; - - lockcount--; - - if (lockcount > 0) - return; - - if (lockcount < 0) - Sys_Error ("Unbalanced unlock"); - - MGL_endDirectAccess(); - -// to turn up any unlocked accesses - vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; - -} - - -int VID_ForceUnlockedAndReturnState (void) -{ - int lk; - - if (!lockcount) - return 0; - - lk = lockcount; - - if (dibdc) - { - lockcount = 0; - } - else - { - lockcount = 1; - VID_UnlockBuffer (); - } - - return lk; -} - - -void VID_ForceLockState (int lk) -{ - - if (!dibdc && lk) - { - lockcount = 0; - VID_LockBuffer (); - } - - lockcount = lk; -} - - -void VID_SetPalette (unsigned char *palette) -{ - INT i; - palette_t pal[256]; - HDC hdc; - - if (!Minimized) - { - palette_changed = true; - - // make sure we have the static colors if we're the active app - hdc = GetDC(NULL); - - if (vid_palettized && ActiveApp) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - - ReleaseDC(NULL,hdc); - - // Translate the palette values to an MGL palette array and - // set the values. - for (i = 0; i < 256; i++) - { - pal[i].red = palette[i*3]; - pal[i].green = palette[i*3+1]; - pal[i].blue = palette[i*3+2]; - } - - if (DDActive) - { - if (!mgldc) - return; - - MGL_setPalette(mgldc,pal,256,0); - MGL_realizePalette(mgldc,256,0,false); - if (memdc) - MGL_setPalette(memdc,pal,256,0); - } - else - { - if (!windc) - return; - - MGL_setPalette(windc,pal,256,0); - MGL_realizePalette(windc,256,0,false); - if (dibdc) - { - MGL_setPalette(dibdc,pal,256,0); - MGL_realizePalette(dibdc,256,0,false); - } - } - } - - memcpy (vid_curpal, palette, sizeof(vid_curpal)); - - if (syscolchg) - { - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - syscolchg = false; - } -} - - -void VID_ShiftPalette (unsigned char *palette) -{ - VID_SetPalette (palette); -} - - -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void VID_DescribeCurrentMode_f (void) -{ - Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); -} - - -/* -================= -VID_NumModes_f -================= -*/ -void VID_NumModes_f (void) -{ - - if (nummodes == 1) - Con_Printf ("%d video mode is available\n", nummodes); - else - Con_Printf ("%d video modes are available\n", nummodes); -} - - -/* -================= -VID_DescribeMode_f -================= -*/ -void VID_DescribeMode_f (void) -{ - int modenum; - - modenum = Q_atoi (Cmd_Argv(1)); - - Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void VID_DescribeModes_f (void) -{ - int i, lnummodes; - char *pinfo; - qboolean na; - vmode_t *pv; - - na = false; - - lnummodes = VID_NumModes (); - - for (i=0 ; iwidth, pv->height)) - { - Con_Printf ("%2d: %s\n", i, pinfo); - } - else - { - Con_Printf ("**: %s\n", pinfo); - na = true; - } - } - - if (na) - { - Con_Printf ("\n[**: not enough system RAM for mode]\n"); - } -} - - -/* -================= -VID_TestMode_f -================= -*/ -void VID_TestMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - if (VID_SetMode (modenum, vid_curpal)) - { - vid_testingmode = 1; - testduration = Q_atof (Cmd_Argv(2)); - if (testduration == 0) - testduration = 5.0; - vid_testendtime = realtime + testduration; - } - } -} - - -/* -================= -VID_Windowed_f -================= -*/ -void VID_Windowed_f (void) -{ - - VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); -} - - -/* -================= -VID_Fullscreen_f -================= -*/ -void VID_Fullscreen_f (void) -{ - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); -} - - -/* -================= -VID_Minimize_f -================= -*/ -void VID_Minimize_f (void) -{ - -// we only support minimizing windows; if you're fullscreen, -// switch to windowed first - if (modestate == MS_WINDOWED) - ShowWindow (mainwindow, SW_MINIMIZE); -} - - - -/* -================= -VID_ForceMode_f -================= -*/ -void VID_ForceMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) - { - modenum = Q_atoi (Cmd_Argv(1)); - - force_mode_set = 1; - VID_SetMode (modenum, vid_curpal); - force_mode_set = 0; - } -} - - -void VID_Init (unsigned char *palette) -{ - int i, bestmatch, bestmatchmetric, t, dr, dg, db; - int basenummodes; - byte *ptmp; - - Cvar_RegisterVariable (&vid_mode); - Cvar_RegisterVariable (&vid_wait); - Cvar_RegisterVariable (&vid_nopageflip); - Cvar_RegisterVariable (&_vid_wait_override); - Cvar_RegisterVariable (&_vid_default_mode); - Cvar_RegisterVariable (&_vid_default_mode_win); - Cvar_RegisterVariable (&vid_config_x); - Cvar_RegisterVariable (&vid_config_y); - Cvar_RegisterVariable (&vid_stretch_by_2); - Cvar_RegisterVariable (&_windowed_mouse); - Cvar_RegisterVariable (&vid_fullscreen_mode); - Cvar_RegisterVariable (&vid_windowed_mode); - Cvar_RegisterVariable (&block_switch); - Cvar_RegisterVariable (&vid_window_x); - Cvar_RegisterVariable (&vid_window_y); - - Cmd_AddCommand ("vid_testmode", VID_TestMode_f); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); - Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); - Cmd_AddCommand ("vid_windowed", VID_Windowed_f); - Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); - Cmd_AddCommand ("vid_minimize", VID_Minimize_f); - - if (COM_CheckParm ("-dibonly")) - dibonly = true; - - VID_InitMGLDIB (global_hInstance); - - basenummodes = nummodes; - - if (!dibonly) - VID_InitMGLFull (global_hInstance); - -// if there are no non-windowed modes, or only windowed and mode 0x13, then use -// fullscreen DIBs as well - if (((nummodes == basenummodes) || - ((nummodes == (basenummodes + 1)) && is_mode0x13)) && - !COM_CheckParm ("-nofulldib")) - - { - VID_InitFullDIB (global_hInstance); - } - - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); - vid_testingmode = 0; - -// GDI doesn't let us remap palette index 0, so we'll remap color -// mappings from that black to another one - bestmatchmetric = 256*256*3; - - for (i=1 ; i<256 ; i++) - { - dr = palette[0] - palette[i*3]; - dg = palette[1] - palette[i*3+1]; - db = palette[2] - palette[i*3+2]; - - t = (dr * dr) + (dg * dg) + (db * db); - - if (t < bestmatchmetric) - { - bestmatchmetric = t; - bestmatch = i; - - if (t == 0) - break; - } - } - - for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) - { - if (*ptmp == 0) - *ptmp = bestmatch; - } - - if (COM_CheckParm("-startwindowed")) - { - startwindowed = 1; - vid_default = windowed_default; - } - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - -// sound initialization has to go here, preceded by a windowed mode set, -// so there's a window for DirectSound to work with but we're not yet -// fullscreen so the "hardware already in use" dialog is visible if it -// gets displayed - -// keep the window minimized until we're ready for the first real mode set - hide_window = true; - VID_SetMode (MODE_WINDOWED, palette); - hide_window = false; - S_Init (); - - vid_initialized = true; - - force_mode_set = true; - VID_SetMode (vid_default, palette); - force_mode_set = false; - - vid_realmode = vid_modenum; - - VID_SetPalette (palette); - - vid_menudrawfn = VID_MenuDraw; - vid_menukeyfn = VID_MenuKey; - - strcpy (badmode.modedesc, "Bad mode"); -} - - -void VID_Shutdown (void) -{ - HDC hdc; - int dummy; - - if (vid_initialized) - { - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); - - AppActivate(false, false); - DestroyDIBWindow (); - DestroyFullscreenWindow (); - DestroyFullDIBWindow (); - - if (hwnd_dialog) - DestroyWindow (hwnd_dialog); - - if (mainwindow) - DestroyWindow(mainwindow); - - MGL_exit(); - - vid_testingmode = 0; - vid_initialized = 0; - } -} - - -/* -================ -FlipScreen -================ -*/ -void FlipScreen(vrect_t *rects) -{ - HRESULT ddrval; - - // Flip the surfaces - - if (DDActive) - { - if (mgldc) - { - if (memdc) - { - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(mgldc, memdc, - rects->x, - rects->y, - rects->x + rects->width, - rects->y + rects->height, - rects->x << 1, - rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(mgldc, memdc, - rects->x, rects->y, - (rects->x + rects->width), - (rects->y + rects->height), - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - if (vid.numpages > 1) - { - // We have a flipping surface, so do a hard page flip - aPage = (aPage+1) % vid.numpages; - vPage = (vPage+1) % vid.numpages; - MGL_setActivePage(mgldc,aPage); - MGL_setVisualPage(mgldc,vPage,waitVRT); - } - } - } - else - { - HDC hdcScreen; - - hdcScreen = GetDC(mainwindow); - - if (windc && dibdc) - { - MGL_setWinDC(windc,hdcScreen); - - while (rects) - { - if (vid_stretched) - { - MGL_stretchBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x << 1, rects->y << 1, - (rects->x + rects->width) << 1, - (rects->y + rects->height) << 1); - } - else - { - MGL_bitBltCoord(windc,dibdc, - rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - rects->x, rects->y, MGL_REPLACE_MODE); - } - - rects = rects->pnext; - } - } - - ReleaseDC(mainwindow, hdcScreen); - } -} - - -void VID_Update (vrect_t *rects) -{ - vrect_t rect; - RECT trect; - - if (!vid_palettized && palette_changed) - { - palette_changed = false; - rect.x = 0; - rect.y = 0; - rect.width = vid.width; - rect.height = vid.height; - rect.pnext = NULL; - rects = ▭ - } - - if (firstupdate) - { - if (modestate == MS_WINDOWED) - { - GetWindowRect (mainwindow, &trect); - - if ((trect.left != (int)vid_window_x.value) || - (trect.top != (int)vid_window_y.value)) - { - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - VID_CheckWindowXY (); - SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, - (int)vid_window_y.value, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - } - } - - if ((_vid_default_mode_win.value != vid_default) && - (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) - { - firstupdate = 0; - - if (COM_CheckParm ("-resetwinpos")) - { - Cvar_SetValue ("vid_window_x", 0.0); - Cvar_SetValue ("vid_window_y", 0.0); - } - - if ((_vid_default_mode_win.value < 0) || - (_vid_default_mode_win.value >= nummodes)) - { - Cvar_SetValue ("_vid_default_mode_win", windowed_default); - } - - Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); - } - } - - // We've drawn the frame; copy it to the screen - FlipScreen (rects); - - if (vid_testingmode) - { - if (realtime >= vid_testendtime) - { - VID_SetMode (vid_realmode, vid_curpal); - vid_testingmode = 0; - } - } - else - { - if ((int)vid_mode.value != vid_realmode) - { - VID_SetMode ((int)vid_mode.value, vid_curpal); - Cvar_SetValue ("vid_mode", (float)vid_modenum); - // so if mode set fails, we don't keep on - // trying to set that mode - vid_realmode = vid_modenum; - } - } - -// handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) - { - if ((int)_windowed_mouse.value != windowed_mouse) - { - if (_windowed_mouse.value) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - - windowed_mouse = (int)_windowed_mouse.value; - } - } -} - - -/* -================ -D_BeginDirectRect -================ -*/ -void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j> repshift) * width], - width); - } - } - - VID_UnlockBuffer (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height << repshift; - rect.pnext = NULL; - - FlipScreen (&rect); - } - else - { - // unlock if locked - if (lockcount > 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // save from and draw to screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jsurface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - width); - memcpy ((byte *)mgldc->surface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &pbitmap[(i >> repshift) * width], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -/* -================ -D_EndDirectRect -================ -*/ -void D_EndDirectRect (int x, int y, int width, int height) -{ - int i, j, reps, repshift; - vrect_t rect; - - if (!vid_initialized) - return; - - if (vid.aspect > 1.5) - { - reps = 2; - repshift = 1; - } - else - { - reps = 1; - repshift = 0; - } - - if (vid.numpages == 1) - { - VID_LockBuffer (); - - if (!vid.direct) - Sys_Error ("NULL vid.direct pointer"); - - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; j 0) - MGL_endDirectAccess(); - - // set the active page to the displayed page - MGL_setActivePage (mgldc, vPage); - - // lock the screen - MGL_beginDirectAccess (); - - // restore to the screen - for (i=0 ; i<(height << repshift) ; i += reps) - { - for (j=0 ; jsurface + x + - ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, - &backingbuf[(i + j) * 24], - width); - } - } - - // unlock the screen - MGL_endDirectAccess (); - - // restore the original active page - MGL_setActivePage (mgldc, aPage); - - // relock the screen if it was locked - if (lockcount > 0) - MGL_beginDirectAccess(); - } -} - - -//========================================================================== - -byte scantokey[128] = - { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0 , 27, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1 - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2 - 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*', - K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 - K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME, - K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 - K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, - K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 -}; - -/* -======= -MapKey - -Map from windows to quake keynums -======= -*/ -int MapKey (int key) -{ - key = (key>>16)&255; - if (key > 127) - return 0; - - return scantokey[key]; -} - -void AppActivate(BOOL fActive, BOOL minimize) -/**************************************************************************** -* -* Function: AppActivate -* Parameters: fActive - True if app is activating -* -* Description: If the application is activating, then swap the system -* into SYSPAL_NOSTATIC mode so that our palettes will display -* correctly. -* -****************************************************************************/ -{ - HDC hdc; - int i, t; - static BOOL sound_active; - - ActiveApp = fActive; - -// messy, but it seems to work - if (vid_fulldib_on_focus_mode) - { - Minimized = minimize; - - if (Minimized) - ActiveApp = false; - } - - MGL_appActivate(windc, ActiveApp); - - if (vid_initialized) - { - // yield the palette if we're losing the focus - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - { - if (ActiveApp) - { - if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) - { - // switch to SYSPAL_NOSTATIC and remap the colors - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - syscolchg = true; - pal_is_nostatic = true; - } - } - } - else if (pal_is_nostatic) - { - if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) - { - // switch back to SYSPAL_STATIC and the old mapping - SetSystemPaletteUse(hdc, SYSPAL_STATIC); - syscolchg = true; - } - - pal_is_nostatic = false; - } - } - - if (!Minimized) - VID_SetPalette (vid_curpal); - - scr_fullupdate = 0; - - ReleaseDC(NULL,hdc); - } - -// enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) - { - S_BlockSound (); - S_ClearBuffer (); - sound_active = false; - } - else if (ActiveApp && !sound_active) - { - S_UnblockSound (); - S_ClearBuffer (); - sound_active = true; - } - -// minimize/restore fulldib windows/mouse-capture normal windows on demand - if (!in_mode_set) - { - if (ActiveApp) - { - if (vid_fulldib_on_focus_mode) - { - if (vid_initialized) - { - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); - msg_suppress_1 = false; - - t = in_mode_set; - in_mode_set = true; - AppActivate (true, false); - in_mode_set = t; - } - - IN_ActivateMouse (); - IN_HideMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } - - if (!ActiveApp) - { - if (modestate == MS_FULLDIB) - { - if (vid_initialized) - { - force_minimized = true; - i = vid_fulldib_on_focus_mode; - msg_suppress_1 = true; // don't want to see normal mode set message - VID_SetMode (windowed_default, vid_curpal); - msg_suppress_1 = false; - vid_fulldib_on_focus_mode = i; - force_minimized = false; - - // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll - // do it manually - t = in_mode_set; - in_mode_set = true; - AppActivate (false, true); - in_mode_set = t; - } - - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } -} - - -/* -================ -VID_HandlePause -================ -*/ -void VID_HandlePause (qboolean pause) -{ - - if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - if (pause) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - else - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } -} - - -/* -=================================================================== - -MAIN WINDOW - -=================================================================== -*/ - -LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -/* main window procedure */ -LONG WINAPI MainWndProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LONG lRet = 0; - int fwKeys, xPos, yPos, fActive, fMinimized, temp; - HDC hdc; - PAINTSTRUCT ps; - static int recursiveflag; - - switch (uMsg) - { - case WM_CREATE: - break; - - case WM_SYSCOMMAND: - - // Check for maximize being hit - switch (wParam & ~0x0F) - { - case SC_MAXIMIZE: - // if minimized, bring up as a window before going fullscreen, - // so MGL will have the right state to restore - if (Minimized) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - - VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); - break; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - if (modestate != MS_WINDOWED) - { - // don't call DefWindowProc() because we don't want to start - // the screen saver fullscreen - break; - } - - // fall through windowed and allow the screen saver to start - - default: - if (!in_mode_set) - { - S_BlockSound (); - S_ClearBuffer (); - } - - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - - if (!in_mode_set) - { - S_UnblockSound (); - } - } - break; - - case WM_MOVE: - window_x = (int) LOWORD(lParam); - window_y = (int) HIWORD(lParam); - VID_UpdateWindowStatus (); - - if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) - VID_RememberWindowPos (); - - break; - - case WM_SIZE: - Minimized = false; - - if (!(wParam & SIZE_RESTORED)) - { - if (wParam & SIZE_MINIMIZED) - Minimized = true; - } - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening - break; - - case WM_ACTIVATE: - fActive = LOWORD(wParam); - fMinimized = (BOOL) HIWORD(wParam); - AppActivate(!(fActive == WA_INACTIVE), fMinimized); - - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - if (!in_mode_set) - { - if (windc) - MGL_activatePalette(windc,true); - - VID_SetPalette(vid_curpal); - } - - break; - - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - - if (!in_mode_set && host_initialized) - SCR_UpdateWholeScreen (); - - EndPaint(hWnd, &ps); - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (!in_mode_set) - Key_Event (MapKey(lParam), true); - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - if (!in_mode_set) - Key_Event (MapKey(lParam), false); - break; - - // this is complicated because Win32 seems to pack multiple mouse events into - // one update sometimes, so we always check all states and look for events - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEMOVE: - if (!in_mode_set) - { - temp = 0; - - if (wParam & MK_LBUTTON) - temp |= 1; - - if (wParam & MK_RBUTTON) - temp |= 2; - - if (wParam & MK_MBUTTON) - temp |= 4; - - IN_MouseEvent (temp); - } - break; - - // JACK: This is the mouse wheel with the Intellimouse - // Its delta is either positive or neg, and we generate the proper - // Event. - case WM_MOUSEWHEEL: - if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); - } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); - } - break; - // KJB: Added these new palette functions - case WM_PALETTECHANGED: - if ((HWND)wParam == hWnd) - break; - /* Fall through to WM_QUERYNEWPALETTE */ - case WM_QUERYNEWPALETTE: - hdc = GetDC(NULL); - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - ReleaseDC(NULL,hdc); - - scr_fullupdate = 0; - - if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) - { - VID_SetPalette (vid_curpal); - InvalidateRect (mainwindow, NULL, false); - - // specifically required if WM_QUERYNEWPALETTE realizes a new palette - lRet = TRUE; - } - break; - - case WM_DISPLAYCHANGE: - if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) - { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - break; - - case WM_CLOSE: - // this causes Close in the right-click task bar menu not to work, but right - // now bad things happen if Close is handled in that case (garbage and a - // crash on Win95) - if (!in_mode_set) - { - if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) - { - Sys_Quit (); - } - } - break; - - case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); - break; - - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - break; - } - - /* return 0 if handled message, 1 if not */ - return lRet; -} - - -extern void M_Menu_Options_f (void); -extern void M_Print (int cx, int cy, char *str); -extern void M_PrintWhite (int cx, int cy, char *str); -extern void M_DrawCharacter (int cx, int line, int num); -extern void M_DrawTransPic (int x, int y, qpic_t *pic); -extern void M_DrawPic (int x, int y, qpic_t *pic); - -static int vid_line, vid_wmodes; - -typedef struct -{ - int modenum; - char *desc; - int iscur; - int ismode13; - int width; -} modedesc_t; - -#define MAX_COLUMN_SIZE 5 -#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) -#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) - -static modedesc_t modedescs[MAX_MODEDESCS]; - -/* -================ -VID_MenuDraw -================ -*/ -void VID_MenuDraw (void) -{ - qpic_t *p; - char *ptr; - int lnummodes, i, j, k, column, row, dup, dupmode; - char temp[100]; - vmode_t *pv; - modedesc_t tmodedesc; - - p = Draw_CachePic ("gfx/vidmodes.lmp"); - M_DrawPic ( (320-p->width)/2, 4, p); - - for (i=0 ; i<3 ; i++) - { - ptr = VID_GetModeDescriptionMemCheck (i); - modedescs[i].modenum = modelist[i].modenum; - modedescs[i].desc = ptr; - modedescs[i].ismode13 = 0; - modedescs[i].iscur = 0; - - if (vid_modenum == i) - modedescs[i].iscur = 1; - } - - vid_wmodes = 3; - lnummodes = VID_NumModes (); - - for (i=3 ; iwidth != 360) || COM_CheckParm("-allow360"))) - { - dup = 0; - - for (j=3 ; jmode13; - modedescs[k].iscur = 0; - modedescs[k].width = pv->width; - - if (i == vid_modenum) - modedescs[k].iscur = 1; - - if (!dup) - vid_wmodes++; - } - } - } - } - -// sort the modes on width (to handle picking up oddball dibonly modes -// after all the others) - for (i=3 ; i<(vid_wmodes-1) ; i++) - { - for (j=(i+1) ; j modedescs[j].width) - { - tmodedesc = modedescs[i]; - modedescs[i] = modedescs[j]; - modedescs[j] = tmodedesc; - } - } - } - - - M_Print (13*8, 36, "Windowed Modes"); - - column = 16; - row = 36+2*8; - - for (i=0 ; i<3; i++) - { - if (modedescs[i].iscur) - M_PrintWhite (column, row, modedescs[i].desc); - else - M_Print (column, row, modedescs[i].desc); - - column += 13*8; - } - - if (vid_wmodes > 3) - { - M_Print (12*8, 36+4*8, "Fullscreen Modes"); - - column = 16; - row = 36+6*8; - - for (i=3 ; i= 3) - row += 3*8; - - M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); - } -} - - -/* -================ -VID_MenuKey -================ -*/ -void VID_MenuKey (int key) -{ - if (vid_testingmode) - return; - - switch (key) - { - case K_ESCAPE: - S_LocalSound ("misc/menu1.wav"); - M_Menu_Options_f (); - break; - - case K_LEFTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 2) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = vid_wmodes - 1; - break; - - case K_RIGHTARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + - ((vid_line + 4) % VID_ROW_SIZE); - - if (vid_line >= vid_wmodes) - vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; - break; - - case K_UPARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line -= VID_ROW_SIZE; - - if (vid_line < 0) - { - vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line >= vid_wmodes) - vid_line -= VID_ROW_SIZE; - } - break; - - case K_DOWNARROW: - S_LocalSound ("misc/menu1.wav"); - vid_line += VID_ROW_SIZE; - - if (vid_line >= vid_wmodes) - { - vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / - VID_ROW_SIZE) * VID_ROW_SIZE; - - while (vid_line < 0) - vid_line += VID_ROW_SIZE; - } - break; - - case K_ENTER: - S_LocalSound ("misc/menu1.wav"); - VID_SetMode (modedescs[vid_line].modenum, vid_curpal); - break; - - case 'T': - case 't': - S_LocalSound ("misc/menu1.wav"); - // have to set this before setting the mode because WM_PAINT - // happens during the mode set and does a VID_Update, which - // checks vid_testingmode - vid_testingmode = 1; - vid_testendtime = realtime + 5.0; - - if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) - { - vid_testingmode = 0; - } - break; - - case 'D': - case 'd': - S_LocalSound ("misc/menu1.wav"); - firstupdate = 0; - Cvar_SetValue ("_vid_default_mode_win", vid_modenum); - break; - - default: - break; - } -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// vid_win.c -- Win32 video driver + +#include "quakedef.h" +#include "winquake.h" +#include "d_local.h" +#include "resource.h" + +#define MAX_MODE_LIST 30 +#define VID_ROW_SIZE 3 + +qboolean dibonly; + +extern int Minimized; + +HWND mainwindow; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); + +int DIBWidth, DIBHeight; +qboolean DDActive; +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +int window_center_x, window_center_y, window_x, window_y, window_width, window_height; +RECT window_rect; + +static DEVMODE gdevmode; +static qboolean startwindowed = 0, windowed_mode_set; +static int firstupdate = 1; +static qboolean vid_initialized = false, vid_palettized; +static int lockcount; +static int vid_fulldib_on_focus_mode; +static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; +static int vid_stretched, windowed_mouse; +static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; +static HICON hIcon; + +viddef_t vid; // global video state + +#define MODE_WINDOWED 0 +#define MODE_SETTABLE_WINDOW 2 +#define NO_MODE (MODE_WINDOWED - 1) +#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) + +// Note that 0 is MODE_WINDOWED +cvar_t vid_mode = {"vid_mode","0", false}; +// Note that 0 is MODE_WINDOWED +cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; +// Note that 3 is MODE_FULLSCREEN_DEFAULT +cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; +cvar_t vid_wait = {"vid_wait","0"}; +cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; +cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; +cvar_t vid_config_x = {"vid_config_x","800", true}; +cvar_t vid_config_y = {"vid_config_y","600", true}; +cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; +cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; +cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; +cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; +cvar_t block_switch = {"block_switch","0", true}; +cvar_t vid_window_x = {"vid_window_x", "0", true}; +cvar_t vid_window_y = {"vid_window_y", "0", true}; + +typedef struct { + int width; + int height; +} lmode_t; + +lmode_t lowresmodes[] = { + {320, 200}, + {320, 240}, + {400, 300}, + {512, 384}, +}; + +int vid_modenum = NO_MODE; +int vid_testingmode, vid_realmode; +double vid_testendtime; +int vid_default = MODE_WINDOWED; +static int windowed_default; + +modestate_t modestate = MS_UNINIT; + +static byte *vid_surfcache; +static int vid_surfcachesize; +static int VID_highhunkmark; + +unsigned char vid_curpal[256*3]; + +unsigned short d_8to16table[256]; +unsigned d_8to24table[256]; + +int driver = grDETECT,mode; +bool useWinDirect = true, useDirectDraw = true; +MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; + +typedef struct { + modestate_t type; + int width; + int height; + int modenum; + int mode13; + int stretched; + int dib; + int fullscreen; + int bpp; + int halfscreen; + char modedesc[13]; +} vmode_t; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; +static vmode_t *pcurrentmode; + +int aPage; // Current active display page +int vPage; // Current visible display page +int waitVRT = true; // True to wait for retrace on flip + +static vmode_t badmode; + +static byte backingbuf[48*24]; + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void AppActivate(BOOL fActive, BOOL minimize); + + +/* +================ +VID_RememberWindowPos +================ +*/ +void VID_RememberWindowPos (void) +{ + RECT rect; + + if (GetWindowRect (mainwindow, &rect)) + { + if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && + (rect.top < GetSystemMetrics (SM_CYSCREEN)) && + (rect.right > 0) && + (rect.bottom > 0)) + { + Cvar_SetValue ("vid_window_x", (float)rect.left); + Cvar_SetValue ("vid_window_y", (float)rect.top); + } + } +} + + +/* +================ +VID_CheckWindowXY +================ +*/ +void VID_CheckWindowXY (void) +{ + + if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + ((int)vid_window_x.value < 0) || + ((int)vid_window_y.value < 0)) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0 ); + } +} + + +/* +================ +VID_UpdateWindowStatus +================ +*/ +void VID_UpdateWindowStatus (void) +{ + + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + + IN_UpdateClipCursor (); +} + + +/* +================ +ClearAllStates +================ +*/ +void ClearAllStates (void) +{ + int i; + +// send an up event for each key, to make sure the server clears them all + for (i=0 ; i<256 ; i++) + { + Key_Event (i, false); + } + + Key_ClearStates (); + IN_ClearStates (); +} + + +/* +================ +VID_CheckAdequateMem +================ +*/ +qboolean VID_CheckAdequateMem (int width, int height) +{ + int tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + tbuffersize += D_SurfaceCacheForRes (width, height); + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < minimum_memory) + { + return false; // not enough memory for mode + } + + return true; +} + + +/* +================ +VID_AllocBuffers +================ +*/ +qboolean VID_AllocBuffers (int width, int height) +{ + int tsize, tbuffersize; + + tbuffersize = width * height * sizeof (*d_pzbuffer); + + tsize = D_SurfaceCacheForRes (width, height); + + tbuffersize += tsize; + +// see if there's enough memory, allowing for the normal mode 0x13 pixel, +// z, and surface buffers + if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + + 0x10000 * 3) < minimum_memory) + { + Con_SafePrintf ("Not enough memory for video mode\n"); + return false; // not enough memory for mode + } + + vid_surfcachesize = tsize; + + if (d_pzbuffer) + { + D_FlushCaches (); + Hunk_FreeToHighMark (VID_highhunkmark); + d_pzbuffer = NULL; + } + + VID_highhunkmark = Hunk_HighMark (); + + d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); + + vid_surfcache = (byte *)d_pzbuffer + + width * height * sizeof (*d_pzbuffer); + + return true; +} + + +void initFatalError(void) +{ + MGL_exit(); + MGL_fatalError(MGL_errorMsg(MGL_result())); + exit(EXIT_FAILURE); +} + + +int VID_Suspend (MGLDC *dc,m_int flags) +{ + + if (flags & MGL_DEACTIVATE) + { + // FIXME: this doesn't currently work on NT + if (block_switch.value && !WinNT) + { + return MGL_NO_DEACTIVATE; + } + + S_BlockSound (); + S_ClearBuffer (); + + IN_RestoreOriginalMouseState (); + CDAudio_Pause (); + + // keep WM_PAINT from trying to redraw + in_mode_set = true; + + block_drawing = true; // so we don't try to draw while switched away + + return MGL_NO_SUSPEND_APP; + } + else if (flags & MGL_REACTIVATE) + { + IN_SetQuakeMouseState (); + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + CDAudio_Resume (); + S_UnblockSound (); + + in_mode_set = false; + + vid.recalc_refdef = 1; + + block_drawing = false; + + return MGL_NO_SUSPEND_APP; + } + +} + + +void registerAllDispDrivers(void) +{ + /* Event though these driver require WinDirect, we register + * them so that they will still be available even if DirectDraw + * is present and the user has disable the high performance + * WinDirect modes. + */ + MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); +// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); + + /* Register display drivers */ + if (useWinDirect) + { +//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); + MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); + + if (!COM_CheckParm ("-novbeaf")) + MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); + } + + if (useDirectDraw) + { + MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); + } +} + + +void registerAllMemDrivers(void) +{ + /* Register memory context drivers */ + MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); +} + + +void VID_InitMGLFull (HINSTANCE hInstance) +{ + int i, xRes, yRes, bits, vMode, lowres, curmode, temp; + int lowstretchedres, stretchedmode, lowstretched; + uchar *m; + +// FIXME: NT is checked for because MGL currently has a bug that causes it +// to try to use WinDirect modes even on NT + if (COM_CheckParm("-nowindirect") || + COM_CheckParm("-nowd") || + COM_CheckParm("-novesa") || + WinNT) + { + useWinDirect = false; + } + + if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) + useDirectDraw = false; + + // Initialise the MGL + MGL_unregisterAllDrivers(); + registerAllDispDrivers(); + registerAllMemDrivers(); + MGL_detectGraph(&driver,&mode); + m = MGL_availableModes(); + + if (m[0] != 0xFF) + { + lowres = lowstretchedres = 99999; + lowstretched = 0; + curmode = 0; + + // find the lowest-res mode, or a mode we can stretch up to and get + // lowest-res that way + for (i = 0; m[i] != 0xFF; i++) + { + MGL_modeResolution(m[i], &xRes, &yRes,&bits); + + if ((bits == 8) && + (xRes <= MAXWIDTH) && + (yRes <= MAXHEIGHT) && + (curmode < MAX_MODE_LIST)) + { + if (m[i] == grVGA_320x200x256) + is_mode0x13 = true; + + if (!COM_CheckParm("-noforcevga")) + { + if (m[i] == grVGA_320x200x256) + { + mode = i; + break; + } + } + + if (xRes < lowres) + { + lowres = xRes; + mode = i; + } + + if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) + { + lowstretchedres = xRes >> 1; + stretchedmode = i; + } + } + + curmode++; + } + + // if there's a mode we can stretch by 2 up to, thereby effectively getting + // a lower-res mode than the lowest-res real but still at least 320x200, that + // will be our default mode + if (lowstretchedres < lowres) + { + mode = stretchedmode; + lowres = lowstretchedres; + lowstretched = 1; + } + + // build the mode list, leaving room for the low-res stretched mode, if any + nummodes++; // leave room for default mode + + for (i = 0; m[i] != 0xFF; i++) + { + MGL_modeResolution(m[i], &xRes, &yRes,&bits); + + if ((bits == 8) && + (xRes <= MAXWIDTH) && + (yRes <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) + { + if (i == mode) + { + if (lowstretched) + { + stretchedmode = nummodes; + curmode = nummodes++; + } + else + { + curmode = MODE_FULLSCREEN_DEFAULT; + } + } + else + { + curmode = nummodes++; + } + + modelist[curmode].type = MS_FULLSCREEN; + modelist[curmode].width = xRes; + modelist[curmode].height = yRes; + sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); + + if (m[i] == grVGA_320x200x256) + modelist[curmode].mode13 = 1; + else + modelist[curmode].mode13 = 0; + + modelist[curmode].modenum = m[i]; + modelist[curmode].stretched = 0; + modelist[curmode].dib = 0; + modelist[curmode].fullscreen = 1; + modelist[curmode].halfscreen = 0; + modelist[curmode].bpp = 8; + } + } + + if (lowstretched) + { + modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; + modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; + modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; + modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; + sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", + modelist[MODE_FULLSCREEN_DEFAULT].width, + modelist[MODE_FULLSCREEN_DEFAULT].height); + } + + vid_default = MODE_FULLSCREEN_DEFAULT; + + temp = m[0]; + + if (!MGL_init(&driver, &temp, "")) + { + initFatalError(); + } + } + + MGL_setSuspendAppCallback(VID_Suspend); +} + + +MGLDC *createDisplayDC(int forcemem) +/**************************************************************************** +* +* Function: createDisplayDC +* Returns: Pointer to the MGL device context to use for the application +* +* Description: Initialises the MGL and creates an appropriate display +* device context to be used by the GUI. This creates and +* apropriate device context depending on the system being +* compile for, and should be the only place where system +* specific code is required. +* +****************************************************************************/ +{ + MGLDC *dc; + pixel_format_t pf; + int npages; + + // Start the specified video mode + if (!MGL_changeDisplayMode(mode)) + initFatalError(); + + npages = MGL_availablePages(mode); + + if (npages > 3) + npages = 3; + + if (!COM_CheckParm ("-notriplebuf")) + { + if (npages > 2) + { + npages = 2; + } + } + + if ((dc = MGL_createDisplayDC(npages)) == NULL) + return NULL; + + if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) + { + MGL_makeCurrentDC(dc); + memdc = NULL; + } + else + { + // Set up for blitting from a memory buffer + memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); + MGL_makeCurrentDC(memdc); + } + + // Enable page flipping even for even for blitted surfaces + if (forcemem) + { + vid.numpages = 1; + } + else + { + vid.numpages = dc->mi.maxPage + 1; + + if (vid.numpages > 1) + { + // Set up for page flipping + MGL_setActivePage(dc, aPage = 1); + MGL_setVisualPage(dc, vPage = 0, false); + } + + if (vid.numpages > 3) + vid.numpages = 3; + } + + if (vid.numpages == 2) + waitVRT = true; + else + waitVRT = false; + + return dc; +} + + +void VID_InitMGLDIB (HINSTANCE hInstance) +{ + WNDCLASS wc; + HDC hdc; + int i; + + hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + /* Register the frame class */ + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = "WinQuake"; + + if (!RegisterClass (&wc) ) + Sys_Error ("Couldn't register window class"); + + /* Find the size for the DIB window */ + /* Initialise the MGL for windowed operation */ + MGL_setAppInstance(hInstance); + registerAllMemDrivers(); + MGL_initWindowed(""); + + modelist[0].type = MS_WINDOWED; + modelist[0].width = 320; + modelist[0].height = 240; + strcpy (modelist[0].modedesc, "320x240"); + modelist[0].mode13 = 0; + modelist[0].modenum = MODE_WINDOWED; + modelist[0].stretched = 0; + modelist[0].dib = 1; + modelist[0].fullscreen = 0; + modelist[0].halfscreen = 0; + modelist[0].bpp = 8; + + modelist[1].type = MS_WINDOWED; + modelist[1].width = 640; + modelist[1].height = 480; + strcpy (modelist[1].modedesc, "640x480"); + modelist[1].mode13 = 0; + modelist[1].modenum = MODE_WINDOWED + 1; + modelist[1].stretched = 1; + modelist[1].dib = 1; + modelist[1].fullscreen = 0; + modelist[1].halfscreen = 0; + modelist[1].bpp = 8; + + modelist[2].type = MS_WINDOWED; + modelist[2].width = 800; + modelist[2].height = 600; + strcpy (modelist[2].modedesc, "800x600"); + modelist[2].mode13 = 0; + modelist[2].modenum = MODE_WINDOWED + 2; + modelist[2].stretched = 1; + modelist[2].dib = 1; + modelist[2].fullscreen = 0; + modelist[2].halfscreen = 0; + modelist[2].bpp = 8; + +// automatically stretch the default mode up if > 640x480 desktop resolution + hdc = GetDC(NULL); + + if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) + { + vid_default = MODE_WINDOWED + 1; + } + else + { + vid_default = MODE_WINDOWED; + } + + windowed_default = vid_default; + + ReleaseDC(NULL,hdc); + + nummodes = 3; // reserve space for windowed mode + + DDActive = 0; +} + + +/* +================= +VID_InitFullDIB +================= +*/ +void VID_InitFullDIB (HINSTANCE hInstance) +{ + DEVMODE devmode; + int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; + int numlowresmodes, bpp, done; + int cstretch, istretch, mstretch; + BOOL stat; + +// enumerate 8 bpp modes + originalnummodes = nummodes; + modenum = 0; + lowestres = 99999; + + do + { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((devmode.dmBitsPerPel == 8) && + (devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) + { + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].mode13 = 0; + modelist[nummodes].stretched = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = devmode.dmBitsPerPel; + sprintf (modelist[nummodes].modedesc, "%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight); + + // if the width is more than twice the height, reduce it by half because this + // is probably a dual-screen monitor + if (!COM_CheckParm("-noadjustaspect")) + { + if (modelist[nummodes].width > (modelist[nummodes].height << 1)) + { + modelist[nummodes].width >>= 1; + modelist[nummodes].halfscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i=originalnummodes, existingmode = 0 ; i 8 bpp + if (nummodes == originalnummodes) + { + modenum = 0; + lowestres = 99999; + + Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); + + do + { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((((devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT)) || + (!COM_CheckParm("-noadjustaspect") && + (devmode.dmPelsWidth <= (MAXWIDTH*2)) && + (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && + (nummodes < MAX_MODE_LIST) && + (devmode.dmBitsPerPel > 8)) + { + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) + { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].mode13 = 0; + modelist[nummodes].stretched = 0; + modelist[nummodes].halfscreen = 0; + modelist[nummodes].dib = 1; + modelist[nummodes].fullscreen = 1; + modelist[nummodes].bpp = devmode.dmBitsPerPel; + sprintf (modelist[nummodes].modedesc, "%dx%d", + devmode.dmPelsWidth, devmode.dmPelsHeight); + + // if the width is more than twice the height, reduce it by half because this + // is probably a dual-screen monitor + if (!COM_CheckParm("-noadjustaspect")) + { + if (modelist[nummodes].width > (modelist[nummodes].height*2)) + { + modelist[nummodes].width >>= 1; + modelist[nummodes].halfscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + modelist[nummodes].width, + modelist[nummodes].height); + } + } + + for (i=originalnummodes, existingmode = 0 ; i= modelist[i].bpp)) + { + existingmode = 1; + break; + } + } + + if (!existingmode) + { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; + } + } + } + + switch (bpp) + { + case 8: + bpp = 16; + break; + + case 16: + bpp = 32; + break; + + case 32: + done = 1; + break; + } + } + +// now add the lowest stretch-by-2 pseudo-modes between 320-wide +// (inclusive) and lowest real res (not inclusive) +// don't bother if we have a real VGA mode 0x13 mode + if (!is_mode0x13) + { + for (i=originalnummodes, cstretch=0 ; i> 1) < lowestres) && + ((modelist[i].width >> 1) >= 320)) + { + lowestres = modelist[i].width >> 1; + cstretch = 1; + mstretch = i; + } + } + + if ((nummodes + cstretch) > MAX_MODE_LIST) + cstretch = MAX_MODE_LIST - nummodes; + + if (cstretch > 0) + { + for (i=(nummodes-1) ; i>=originalnummodes ; i--) + modelist[i+cstretch] = modelist[i]; + + nummodes += cstretch; + istretch = originalnummodes; + + modelist[istretch] = modelist[mstretch]; + modelist[istretch].width >>= 1; + modelist[istretch].height >>= 1; + modelist[istretch].stretched = 1; + sprintf (modelist[istretch].modedesc, "%dx%d", + modelist[istretch].width, modelist[istretch].height); + } + } + + if (nummodes != originalnummodes) + vid_default = MODE_FULLSCREEN_DEFAULT; + else + Con_SafePrintf ("No fullscreen DIB modes found\n"); +} + + +/* +================= +VID_NumModes +================= +*/ +int VID_NumModes (void) +{ + return nummodes; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t *VID_GetModePtr (int modenum) +{ + + if ((modenum >= 0) && (modenum < nummodes)) + return &modelist[modenum]; + else + return &badmode; +} + + +/* +================= +VID_CheckModedescFixup +================= +*/ +void VID_CheckModedescFixup (int mode) +{ + int x, y, stretch; + + if (mode == MODE_SETTABLE_WINDOW) + { + modelist[mode].stretched = (int)vid_stretch_by_2.value; + stretch = modelist[mode].stretched; + + if (vid_config_x.value < (320 << stretch)) + vid_config_x.value = 320 << stretch; + + if (vid_config_y.value < (200 << stretch)) + vid_config_y.value = 200 << stretch; + + x = (int)vid_config_x.value; + y = (int)vid_config_y.value; + sprintf (modelist[mode].modedesc, "%dx%d", x, y); + modelist[mode].width = x; + modelist[mode].height = y; + } +} + + +/* +================= +VID_GetModeDescriptionMemCheck +================= +*/ +char *VID_GetModeDescriptionMemCheck (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + + if (VID_CheckAdequateMem (pv->width, pv->height)) + { + return pinfo; + } + else + { + return NULL; + } +} + + +/* +================= +VID_GetModeDescription +================= +*/ +char *VID_GetModeDescription (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + return pinfo; +} + + +/* +================= +VID_GetModeDescription2 + +Tacks on "windowed" or "fullscreen" +================= +*/ +char *VID_GetModeDescription2 (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLSCREEN) + { + sprintf(pinfo,"%s fullscreen", pv->modedesc); + } + else if (modelist[mode].type == MS_FULLDIB) + { + sprintf(pinfo,"%s fullscreen", pv->modedesc); + } + else + { + sprintf(pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +// KJB: Added this to return the mode driver name in description for console + +char *VID_GetExtModeDescription (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + + pv = VID_GetModePtr (mode); + if (modelist[mode].type == MS_FULLSCREEN) + { + sprintf(pinfo,"%s fullscreen %s",pv->modedesc, + MGL_modeDriverName(pv->modenum)); + } + else if (modelist[mode].type == MS_FULLDIB) + { + sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); + } + else + { + sprintf(pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +void DestroyDIBWindow (void) +{ + + if (modestate == MS_WINDOWED) + { + // destroy the associated MGL DC's; the window gets reused + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + } +} + + +void DestroyFullscreenWindow (void) +{ + + if (modestate == MS_FULLSCREEN) + { + // destroy the existing fullscreen mode and DC's + if (mgldc) + MGL_destroyDC (mgldc); + if (memdc) + MGL_destroyDC (memdc); + mgldc = memdc = NULL; + } +} + + + +void DestroyFullDIBWindow (void) +{ + if (modestate == MS_FULLDIB) + { + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + // Destroy the fullscreen DIB window and associated MGL DC's + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + } +} + + +qboolean VID_SetWindowedMode (int modenum) +{ + HDC hdc; + pixel_format_t pf; + qboolean stretched; + int lastmodestate; + LONG wlong; + + if (!windowed_mode_set) + { + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + windowed_mode_set; + } + + VID_CheckModedescFixup (modenum); + + DDActive = 0; + lastmodestate = modestate; + + DestroyFullscreenWindow (); + DestroyFullDIBWindow (); + + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + +// KJB: Signal to the MGL that we are going back to windowed mode + if (!MGL_changeDisplayMode(grWINDOWED)) + initFatalError(); + + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + stretched = modelist[modenum].stretched; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + if (stretched) + { + DIBWidth >>= 1; + DIBHeight >>= 1; + } + + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN; + ExWindowStyle = 0; + AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); + +// the first time we're called to set the mode, create the window we'll use +// for the rest of the session + if (!vid_mode_set) + { + mainwindow = CreateWindowEx ( + ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, + NULL, + global_hInstance, + NULL); + + if (!mainwindow) + Sys_Error ("Couldn't create DIB window"); + + // tell MGL to use this window for fullscreen modes + MGL_registerFullScreenWindow (mainwindow); + + vid_mode_set = true; + } + else + { + SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); + } + + if (!SetWindowPos (mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER | + SWP_HIDEWINDOW)) + { + Sys_Error ("Couldn't resize DIB window"); + } + + if (hide_window) + return true; + +// position and show the DIB window + VID_CheckWindowXY (); + SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, + (int)vid_window_y.value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + + if (force_minimized) + ShowWindow (mainwindow, SW_MINIMIZE); + else + ShowWindow (mainwindow, SW_SHOWDEFAULT); + + UpdateWindow (mainwindow); + + modestate = MS_WINDOWED; + vid_fulldib_on_focus_mode = 0; + +// because we have set the background brush for the window to NULL +// (to avoid flickering when re-sizing the window on the desktop), +// we clear the window to black when created, otherwise it will be +// empty while Quake starts up. + hdc = GetDC(mainwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(mainwindow, hdc); + + /* Create the MGL window DC and the MGL memory DC */ + if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) + MGL_fatalError("Unable to create Windowed DC!"); + + if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) + MGL_fatalError("Unable to create Memory DC!"); + + MGL_makeCurrentDC(dibdc); + + vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; + vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; + vid.numpages = 1; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.height = vid.conheight = DIBHeight; + vid.width = vid.conwidth = DIBWidth; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = stretched; + + SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); + + return true; +} + + +qboolean VID_SetFullscreenMode (int modenum) +{ + + DDActive = 1; + + DestroyDIBWindow (); + DestroyFullDIBWindow (); + + mode = modelist[modenum].modenum; + + // Destroy old DC's, resetting back to fullscreen mode + if (mgldc) + MGL_destroyDC (mgldc); + if (memdc) + MGL_destroyDC (memdc); + mgldc = memdc = NULL; + + if ((mgldc = createDisplayDC (modelist[modenum].stretched || + (int)vid_nopageflip.value)) == NULL) + { + return false; + } + + modestate = MS_FULLSCREEN; + vid_fulldib_on_focus_mode = 0; + + vid.buffer = vid.conbuffer = vid.direct = NULL; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + DIBHeight = vid.height = vid.conheight = modelist[modenum].height; + DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = modelist[modenum].stretched; + +// needed because we're not getting WM_MOVE messages fullscreen on NT + window_x = 0; + window_y = 0; + +// set the large icon, so the Quake icon will show up in the taskbar + SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); + SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); + +// shouldn't be needed, but Kendall needs to let us get the activation +// message for this not to be needed on NT + AppActivate (true, false); + + return true; +} + + +qboolean VID_SetFullDIBMode (int modenum) +{ + HDC hdc; + pixel_format_t pf; + int lastmodestate; + + DDActive = 0; + + DestroyFullscreenWindow (); + DestroyDIBWindow (); + + if (windc) + MGL_destroyDC(windc); + if (dibdc) + MGL_destroyDC(dibdc); + windc = dibdc = NULL; + +// KJB: Signal to the MGL that we are going back to windowed mode + if (!MGL_changeDisplayMode(grWINDOWED)) + initFatalError(); + + gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + gdevmode.dmBitsPerPel = modelist[modenum].bpp; + gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << + modelist[modenum].halfscreen; + gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; + gdevmode.dmSize = sizeof (gdevmode); + + if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + Sys_Error ("Couldn't set fullscreen DIB mode"); + + lastmodestate = modestate; + modestate = MS_FULLDIB; + vid_fulldib_on_focus_mode = modenum; + + WindowRect.top = WindowRect.left = 0; + + hdc = GetDC(NULL); + + WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; + WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; + + ReleaseDC(NULL,hdc); + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + ExWindowStyle = 0; + AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); + + SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); + + if (!SetWindowPos (mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER)) + { + Sys_Error ("Couldn't resize DIB window"); + } + +// position and show the DIB window + SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); + ShowWindow (mainwindow, SW_SHOWDEFAULT); + UpdateWindow (mainwindow); + + // Because we have set the background brush for the window to NULL + // (to avoid flickering when re-sizing the window on the desktop), we + // clear the window to black when created, otherwise it will be + // empty while Quake starts up. + hdc = GetDC(mainwindow); + PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); + ReleaseDC(mainwindow, hdc); + + /* Create the MGL window DC and the MGL memory DC */ + if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) + MGL_fatalError("Unable to create Fullscreen DIB DC!"); + + if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) + MGL_fatalError("Unable to create Memory DC!"); + + MGL_makeCurrentDC(dibdc); + + vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; + vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; + vid.numpages = 1; + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.height = vid.conheight = DIBHeight; + vid.width = vid.conwidth = DIBWidth; + vid.aspect = ((float)vid.height / (float)vid.width) * + (320.0 / 240.0); + + vid_stretched = modelist[modenum].stretched; + +// needed because we're not getting WM_MOVE messages fullscreen on NT + window_x = 0; + window_y = 0; + + return true; +} + + +void VID_RestoreOldMode (int original_mode) +{ + static qboolean inerror = false; + + if (inerror) + return; + + in_mode_set = false; + inerror = true; + +// make sure mode set happens (video mode changes) + vid_modenum = original_mode - 1; + + if (!VID_SetMode (original_mode, vid_curpal)) + { + vid_modenum = MODE_WINDOWED - 1; + + if (!VID_SetMode (windowed_default, vid_curpal)) + Sys_Error ("Can't set any video mode"); + } + + inerror = false; +} + + +void VID_SetDefaultMode (void) +{ + + if (vid_initialized) + VID_SetMode (0, vid_curpal); + + IN_DeactivateMouse (); +} + + +int VID_SetMode (int modenum, unsigned char *palette) +{ + int original_mode, temp, dummy; + qboolean stat; + MSG msg; + HDC hdc; + + while ((modenum >= nummodes) || (modenum < 0)) + { + if (vid_modenum == NO_MODE) + { + if (modenum == vid_default) + { + modenum = windowed_default; + } + else + { + modenum = vid_default; + } + + Cvar_SetValue ("vid_mode", (float)modenum); + } + else + { + Cvar_SetValue ("vid_mode", (float)vid_modenum); + return 0; + } + } + + if (!force_mode_set && (modenum == vid_modenum)) + return true; + +// so Con_Printfs don't mess us up by forcing vid and snd updates + temp = scr_disabled_for_loading; + scr_disabled_for_loading = true; + in_mode_set = true; + + CDAudio_Pause (); + S_ClearBuffer (); + + if (vid_modenum == NO_MODE) + original_mode = windowed_default; + else + original_mode = vid_modenum; + + // Set either the fullscreen or windowed mode + if (modelist[modenum].type == MS_WINDOWED) + { + if (_windowed_mouse.value) + { + stat = VID_SetWindowedMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + IN_DeactivateMouse (); + IN_ShowMouse (); + stat = VID_SetWindowedMode(modenum); + } + } + else if (modelist[modenum].type == MS_FULLDIB) + { + stat = VID_SetFullDIBMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + stat = VID_SetFullscreenMode(modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + + window_width = vid.width << vid_stretched; + window_height = vid.height << vid_stretched; + VID_UpdateWindowStatus (); + + CDAudio_Resume (); + scr_disabled_for_loading = temp; + + if (!stat) + { + VID_RestoreOldMode (original_mode); + return false; + } + + if (hide_window) + return true; + +// now we try to make sure we get the focus on the mode switch, because +// sometimes in some systems we don't. We grab the foreground, then +// finish setting up, pump all our messages, and sleep for a little while +// to let messages finish bouncing around the system, then we put +// ourselves at the top of the z order, then grab the foreground again, +// Who knows if it helps, but it probably doesn't hurt + if (!force_minimized) + SetForegroundWindow (mainwindow); + + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + VID_SetPalette (palette); + + ReleaseDC(NULL,hdc); + + vid_modenum = modenum; + Cvar_SetValue ("vid_mode", (float)vid_modenum); + + if (!VID_AllocBuffers (vid.width, vid.height)) + { + // couldn't get memory for this mode; try to fall back to previous mode + VID_RestoreOldMode (original_mode); + return false; + } + + D_InitCaches (vid_surfcache, vid_surfcachesize); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + if (!force_minimized) + { + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (mainwindow); + } + +// fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!msg_suppress_1) + Con_SafePrintf ("%s\n", VID_GetModeDescription (vid_modenum)); + + VID_SetPalette (palette); + + in_mode_set = false; + vid.recalc_refdef = 1; + + return true; +} + +void VID_LockBuffer (void) +{ + + if (dibdc) + return; + + lockcount++; + + if (lockcount > 1) + return; + + MGL_beginDirectAccess(); + + if (memdc) + { + // Update surface pointer for linear access modes + vid.buffer = vid.conbuffer = vid.direct = memdc->surface; + vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; + } + else if (mgldc) + { + // Update surface pointer for linear access modes + vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; + vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; + } + + if (r_dowarp) + d_viewbuffer = r_warpbuffer; + else + d_viewbuffer = (void *)(byte *)vid.buffer; + + if (r_dowarp) + screenwidth = WARP_WIDTH; + else + screenwidth = vid.rowbytes; + + if (lcd_x.value) + screenwidth <<= 1; +} + + +void VID_UnlockBuffer (void) +{ + if (dibdc) + return; + + lockcount--; + + if (lockcount > 0) + return; + + if (lockcount < 0) + Sys_Error ("Unbalanced unlock"); + + MGL_endDirectAccess(); + +// to turn up any unlocked accesses + vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; + +} + + +int VID_ForceUnlockedAndReturnState (void) +{ + int lk; + + if (!lockcount) + return 0; + + lk = lockcount; + + if (dibdc) + { + lockcount = 0; + } + else + { + lockcount = 1; + VID_UnlockBuffer (); + } + + return lk; +} + + +void VID_ForceLockState (int lk) +{ + + if (!dibdc && lk) + { + lockcount = 0; + VID_LockBuffer (); + } + + lockcount = lk; +} + + +void VID_SetPalette (unsigned char *palette) +{ + INT i; + palette_t pal[256]; + HDC hdc; + + if (!Minimized) + { + palette_changed = true; + + // make sure we have the static colors if we're the active app + hdc = GetDC(NULL); + + if (vid_palettized && ActiveApp) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) + { + // switch to SYSPAL_NOSTATIC and remap the colors + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + syscolchg = true; + pal_is_nostatic = true; + } + } + + ReleaseDC(NULL,hdc); + + // Translate the palette values to an MGL palette array and + // set the values. + for (i = 0; i < 256; i++) + { + pal[i].red = palette[i*3]; + pal[i].green = palette[i*3+1]; + pal[i].blue = palette[i*3+2]; + } + + if (DDActive) + { + if (!mgldc) + return; + + MGL_setPalette(mgldc,pal,256,0); + MGL_realizePalette(mgldc,256,0,false); + if (memdc) + MGL_setPalette(memdc,pal,256,0); + } + else + { + if (!windc) + return; + + MGL_setPalette(windc,pal,256,0); + MGL_realizePalette(windc,256,0,false); + if (dibdc) + { + MGL_setPalette(dibdc,pal,256,0); + MGL_realizePalette(dibdc,256,0,false); + } + } + } + + memcpy (vid_curpal, palette, sizeof(vid_curpal)); + + if (syscolchg) + { + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); + syscolchg = false; + } +} + + +void VID_ShiftPalette (unsigned char *palette) +{ + VID_SetPalette (palette); +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void VID_DescribeCurrentMode_f (void) +{ + Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); +} + + +/* +================= +VID_NumModes_f +================= +*/ +void VID_NumModes_f (void) +{ + + if (nummodes == 1) + Con_Printf ("%d video mode is available\n", nummodes); + else + Con_Printf ("%d video modes are available\n", nummodes); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void VID_DescribeMode_f (void) +{ + int modenum; + + modenum = Q_atoi (Cmd_Argv(1)); + + Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void VID_DescribeModes_f (void) +{ + int i, lnummodes; + char *pinfo; + qboolean na; + vmode_t *pv; + + na = false; + + lnummodes = VID_NumModes (); + + for (i=0 ; iwidth, pv->height)) + { + Con_Printf ("%2d: %s\n", i, pinfo); + } + else + { + Con_Printf ("**: %s\n", pinfo); + na = true; + } + } + + if (na) + { + Con_Printf ("\n[**: not enough system RAM for mode]\n"); + } +} + + +/* +================= +VID_TestMode_f +================= +*/ +void VID_TestMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) + { + modenum = Q_atoi (Cmd_Argv(1)); + + if (VID_SetMode (modenum, vid_curpal)) + { + vid_testingmode = 1; + testduration = Q_atof (Cmd_Argv(2)); + if (testduration == 0) + testduration = 5.0; + vid_testendtime = realtime + testduration; + } + } +} + + +/* +================= +VID_Windowed_f +================= +*/ +void VID_Windowed_f (void) +{ + + VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); +} + + +/* +================= +VID_Fullscreen_f +================= +*/ +void VID_Fullscreen_f (void) +{ + + VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); +} + + +/* +================= +VID_Minimize_f +================= +*/ +void VID_Minimize_f (void) +{ + +// we only support minimizing windows; if you're fullscreen, +// switch to windowed first + if (modestate == MS_WINDOWED) + ShowWindow (mainwindow, SW_MINIMIZE); +} + + + +/* +================= +VID_ForceMode_f +================= +*/ +void VID_ForceMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) + { + modenum = Q_atoi (Cmd_Argv(1)); + + force_mode_set = 1; + VID_SetMode (modenum, vid_curpal); + force_mode_set = 0; + } +} + + +void VID_Init (unsigned char *palette) +{ + int i, bestmatch, bestmatchmetric, t, dr, dg, db; + int basenummodes; + byte *ptmp; + + Cvar_RegisterVariable (&vid_mode); + Cvar_RegisterVariable (&vid_wait); + Cvar_RegisterVariable (&vid_nopageflip); + Cvar_RegisterVariable (&_vid_wait_override); + Cvar_RegisterVariable (&_vid_default_mode); + Cvar_RegisterVariable (&_vid_default_mode_win); + Cvar_RegisterVariable (&vid_config_x); + Cvar_RegisterVariable (&vid_config_y); + Cvar_RegisterVariable (&vid_stretch_by_2); + Cvar_RegisterVariable (&_windowed_mouse); + Cvar_RegisterVariable (&vid_fullscreen_mode); + Cvar_RegisterVariable (&vid_windowed_mode); + Cvar_RegisterVariable (&block_switch); + Cvar_RegisterVariable (&vid_window_x); + Cvar_RegisterVariable (&vid_window_y); + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); + Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); + Cmd_AddCommand ("vid_windowed", VID_Windowed_f); + Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); + Cmd_AddCommand ("vid_minimize", VID_Minimize_f); + + if (COM_CheckParm ("-dibonly")) + dibonly = true; + + VID_InitMGLDIB (global_hInstance); + + basenummodes = nummodes; + + if (!dibonly) + VID_InitMGLFull (global_hInstance); + +// if there are no non-windowed modes, or only windowed and mode 0x13, then use +// fullscreen DIBs as well + if (((nummodes == basenummodes) || + ((nummodes == (basenummodes + 1)) && is_mode0x13)) && + !COM_CheckParm ("-nofulldib")) + + { + VID_InitFullDIB (global_hInstance); + } + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + vid_testingmode = 0; + +// GDI doesn't let us remap palette index 0, so we'll remap color +// mappings from that black to another one + bestmatchmetric = 256*256*3; + + for (i=1 ; i<256 ; i++) + { + dr = palette[0] - palette[i*3]; + dg = palette[1] - palette[i*3+1]; + db = palette[2] - palette[i*3+2]; + + t = (dr * dr) + (dg * dg) + (db * db); + + if (t < bestmatchmetric) + { + bestmatchmetric = t; + bestmatch = i; + + if (t == 0) + break; + } + } + + for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) + { + if (*ptmp == 0) + *ptmp = bestmatch; + } + + if (COM_CheckParm("-startwindowed")) + { + startwindowed = 1; + vid_default = windowed_default; + } + + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); + +// sound initialization has to go here, preceded by a windowed mode set, +// so there's a window for DirectSound to work with but we're not yet +// fullscreen so the "hardware already in use" dialog is visible if it +// gets displayed + +// keep the window minimized until we're ready for the first real mode set + hide_window = true; + VID_SetMode (MODE_WINDOWED, palette); + hide_window = false; + S_Init (); + + vid_initialized = true; + + force_mode_set = true; + VID_SetMode (vid_default, palette); + force_mode_set = false; + + vid_realmode = vid_modenum; + + VID_SetPalette (palette); + + vid_menudrawfn = VID_MenuDraw; + vid_menukeyfn = VID_MenuKey; + + strcpy (badmode.modedesc, "Bad mode"); +} + + +void VID_Shutdown (void) +{ + HDC hdc; + int dummy; + + if (vid_initialized) + { + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); + + AppActivate(false, false); + DestroyDIBWindow (); + DestroyFullscreenWindow (); + DestroyFullDIBWindow (); + + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); + + if (mainwindow) + DestroyWindow(mainwindow); + + MGL_exit(); + + vid_testingmode = 0; + vid_initialized = 0; + } +} + + +/* +================ +FlipScreen +================ +*/ +void FlipScreen(vrect_t *rects) +{ + HRESULT ddrval; + + // Flip the surfaces + + if (DDActive) + { + if (mgldc) + { + if (memdc) + { + while (rects) + { + if (vid_stretched) + { + MGL_stretchBltCoord(mgldc, memdc, + rects->x, + rects->y, + rects->x + rects->width, + rects->y + rects->height, + rects->x << 1, + rects->y << 1, + (rects->x + rects->width) << 1, + (rects->y + rects->height) << 1); + } + else + { + MGL_bitBltCoord(mgldc, memdc, + rects->x, rects->y, + (rects->x + rects->width), + (rects->y + rects->height), + rects->x, rects->y, MGL_REPLACE_MODE); + } + + rects = rects->pnext; + } + } + + if (vid.numpages > 1) + { + // We have a flipping surface, so do a hard page flip + aPage = (aPage+1) % vid.numpages; + vPage = (vPage+1) % vid.numpages; + MGL_setActivePage(mgldc,aPage); + MGL_setVisualPage(mgldc,vPage,waitVRT); + } + } + } + else + { + HDC hdcScreen; + + hdcScreen = GetDC(mainwindow); + + if (windc && dibdc) + { + MGL_setWinDC(windc,hdcScreen); + + while (rects) + { + if (vid_stretched) + { + MGL_stretchBltCoord(windc,dibdc, + rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + rects->x << 1, rects->y << 1, + (rects->x + rects->width) << 1, + (rects->y + rects->height) << 1); + } + else + { + MGL_bitBltCoord(windc,dibdc, + rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + rects->x, rects->y, MGL_REPLACE_MODE); + } + + rects = rects->pnext; + } + } + + ReleaseDC(mainwindow, hdcScreen); + } +} + + +void VID_Update (vrect_t *rects) +{ + vrect_t rect; + RECT trect; + + if (!vid_palettized && palette_changed) + { + palette_changed = false; + rect.x = 0; + rect.y = 0; + rect.width = vid.width; + rect.height = vid.height; + rect.pnext = NULL; + rects = ▭ + } + + if (firstupdate) + { + if (modestate == MS_WINDOWED) + { + GetWindowRect (mainwindow, &trect); + + if ((trect.left != (int)vid_window_x.value) || + (trect.top != (int)vid_window_y.value)) + { + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + VID_CheckWindowXY (); + SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, + (int)vid_window_y.value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + } + } + + if ((_vid_default_mode_win.value != vid_default) && + (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) + { + firstupdate = 0; + + if (COM_CheckParm ("-resetwinpos")) + { + Cvar_SetValue ("vid_window_x", 0.0); + Cvar_SetValue ("vid_window_y", 0.0); + } + + if ((_vid_default_mode_win.value < 0) || + (_vid_default_mode_win.value >= nummodes)) + { + Cvar_SetValue ("_vid_default_mode_win", windowed_default); + } + + Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); + } + } + + // We've drawn the frame; copy it to the screen + FlipScreen (rects); + + if (vid_testingmode) + { + if (realtime >= vid_testendtime) + { + VID_SetMode (vid_realmode, vid_curpal); + vid_testingmode = 0; + } + } + else + { + if ((int)vid_mode.value != vid_realmode) + { + VID_SetMode ((int)vid_mode.value, vid_curpal); + Cvar_SetValue ("vid_mode", (float)vid_modenum); + // so if mode set fails, we don't keep on + // trying to set that mode + vid_realmode = vid_modenum; + } + } + +// handle the mouse state when windowed if that's changed + if (modestate == MS_WINDOWED) + { + if ((int)_windowed_mouse.value != windowed_mouse) + { + if (_windowed_mouse.value) + { + IN_ActivateMouse (); + IN_HideMouse (); + } + else + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + + windowed_mouse = (int)_windowed_mouse.value; + } + } +} + + +/* +================ +D_BeginDirectRect +================ +*/ +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (vid.aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (vid.numpages == 1) + { + VID_LockBuffer (); + + if (!vid.direct) + Sys_Error ("NULL vid.direct pointer"); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; j> repshift) * width], + width); + } + } + + VID_UnlockBuffer (); + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height << repshift; + rect.pnext = NULL; + + FlipScreen (&rect); + } + else + { + // unlock if locked + if (lockcount > 0) + MGL_endDirectAccess(); + + // set the active page to the displayed page + MGL_setActivePage (mgldc, vPage); + + // lock the screen + MGL_beginDirectAccess (); + + // save from and draw to screen + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jsurface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + width); + memcpy ((byte *)mgldc->surface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + &pbitmap[(i >> repshift) * width], + width); + } + } + + // unlock the screen + MGL_endDirectAccess (); + + // restore the original active page + MGL_setActivePage (mgldc, aPage); + + // relock the screen if it was locked + if (lockcount > 0) + MGL_beginDirectAccess(); + } +} + + +/* +================ +D_EndDirectRect +================ +*/ +void D_EndDirectRect (int x, int y, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (vid.aspect > 1.5) + { + reps = 2; + repshift = 1; + } + else + { + reps = 1; + repshift = 0; + } + + if (vid.numpages == 1) + { + VID_LockBuffer (); + + if (!vid.direct) + Sys_Error ("NULL vid.direct pointer"); + + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; j 0) + MGL_endDirectAccess(); + + // set the active page to the displayed page + MGL_setActivePage (mgldc, vPage); + + // lock the screen + MGL_beginDirectAccess (); + + // restore to the screen + for (i=0 ; i<(height << repshift) ; i += reps) + { + for (j=0 ; jsurface + x + + ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, + &backingbuf[(i + j) * 24], + width); + } + } + + // unlock the screen + MGL_endDirectAccess (); + + // restore the original active page + MGL_setActivePage (mgldc, aPage); + + // relock the screen if it was locked + if (lockcount > 0) + MGL_beginDirectAccess(); + } +} + + +//========================================================================== + +byte scantokey[128] = + { +// 0 1 2 3 4 5 6 7 +// 8 9 A B C D E F + 0 , 27, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1 + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2 + 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*', + K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 + K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME, + K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 + K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, + K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 +}; + +/* +======= +MapKey + +Map from windows to quake keynums +======= +*/ +int MapKey (int key) +{ + key = (key>>16)&255; + if (key > 127) + return 0; + + return scantokey[key]; +} + +void AppActivate(BOOL fActive, BOOL minimize) +/**************************************************************************** +* +* Function: AppActivate +* Parameters: fActive - True if app is activating +* +* Description: If the application is activating, then swap the system +* into SYSPAL_NOSTATIC mode so that our palettes will display +* correctly. +* +****************************************************************************/ +{ + HDC hdc; + int i, t; + static BOOL sound_active; + + ActiveApp = fActive; + +// messy, but it seems to work + if (vid_fulldib_on_focus_mode) + { + Minimized = minimize; + + if (Minimized) + ActiveApp = false; + } + + MGL_appActivate(windc, ActiveApp); + + if (vid_initialized) + { + // yield the palette if we're losing the focus + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + { + if (ActiveApp) + { + if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) + { + // switch to SYSPAL_NOSTATIC and remap the colors + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + syscolchg = true; + pal_is_nostatic = true; + } + } + } + else if (pal_is_nostatic) + { + if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) + { + // switch back to SYSPAL_STATIC and the old mapping + SetSystemPaletteUse(hdc, SYSPAL_STATIC); + syscolchg = true; + } + + pal_is_nostatic = false; + } + } + + if (!Minimized) + VID_SetPalette (vid_curpal); + + scr_fullupdate = 0; + + ReleaseDC(NULL,hdc); + } + +// enable/disable sound on focus gain/loss + if (!ActiveApp && sound_active) + { + S_BlockSound (); + S_ClearBuffer (); + sound_active = false; + } + else if (ActiveApp && !sound_active) + { + S_UnblockSound (); + S_ClearBuffer (); + sound_active = true; + } + +// minimize/restore fulldib windows/mouse-capture normal windows on demand + if (!in_mode_set) + { + if (ActiveApp) + { + if (vid_fulldib_on_focus_mode) + { + if (vid_initialized) + { + msg_suppress_1 = true; // don't want to see normal mode set message + VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); + msg_suppress_1 = false; + + t = in_mode_set; + in_mode_set = true; + AppActivate (true, false); + in_mode_set = t; + } + + IN_ActivateMouse (); + IN_HideMouse (); + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + { + IN_ActivateMouse (); + IN_HideMouse (); + } + } + + if (!ActiveApp) + { + if (modestate == MS_FULLDIB) + { + if (vid_initialized) + { + force_minimized = true; + i = vid_fulldib_on_focus_mode; + msg_suppress_1 = true; // don't want to see normal mode set message + VID_SetMode (windowed_default, vid_curpal); + msg_suppress_1 = false; + vid_fulldib_on_focus_mode = i; + force_minimized = false; + + // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll + // do it manually + t = in_mode_set; + in_mode_set = true; + AppActivate (false, true); + in_mode_set = t; + } + + IN_DeactivateMouse (); + IN_ShowMouse (); + } + else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + } + } +} + + +/* +================ +VID_HandlePause +================ +*/ +void VID_HandlePause (qboolean pause) +{ + + if ((modestate == MS_WINDOWED) && _windowed_mouse.value) + { + if (pause) + { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + else + { + IN_ActivateMouse (); + IN_HideMouse (); + } + } +} + + +/* +=================================================================== + +MAIN WINDOW + +=================================================================== +*/ + +LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/* main window procedure */ +LONG WINAPI MainWndProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LONG lRet = 0; + int fwKeys, xPos, yPos, fActive, fMinimized, temp; + HDC hdc; + PAINTSTRUCT ps; + static int recursiveflag; + + switch (uMsg) + { + case WM_CREATE: + break; + + case WM_SYSCOMMAND: + + // Check for maximize being hit + switch (wParam & ~0x0F) + { + case SC_MAXIMIZE: + // if minimized, bring up as a window before going fullscreen, + // so MGL will have the right state to restore + if (Minimized) + { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } + + VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); + break; + + case SC_SCREENSAVE: + case SC_MONITORPOWER: + if (modestate != MS_WINDOWED) + { + // don't call DefWindowProc() because we don't want to start + // the screen saver fullscreen + break; + } + + // fall through windowed and allow the screen saver to start + + default: + if (!in_mode_set) + { + S_BlockSound (); + S_ClearBuffer (); + } + + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + + if (!in_mode_set) + { + S_UnblockSound (); + } + } + break; + + case WM_MOVE: + window_x = (int) LOWORD(lParam); + window_y = (int) HIWORD(lParam); + VID_UpdateWindowStatus (); + + if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) + VID_RememberWindowPos (); + + break; + + case WM_SIZE: + Minimized = false; + + if (!(wParam & SIZE_RESTORED)) + { + if (wParam & SIZE_MINIMIZED) + Minimized = true; + } + break; + + case WM_SYSCHAR: + // keep Alt-Space from happening + break; + + case WM_ACTIVATE: + fActive = LOWORD(wParam); + fMinimized = (BOOL) HIWORD(wParam); + AppActivate(!(fActive == WA_INACTIVE), fMinimized); + + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!in_mode_set) + { + if (windc) + MGL_activatePalette(windc,true); + + VID_SetPalette(vid_curpal); + } + + break; + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + + if (!in_mode_set && host_initialized) + SCR_UpdateWholeScreen (); + + EndPaint(hWnd, &ps); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (!in_mode_set) + Key_Event (MapKey(lParam), true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + if (!in_mode_set) + Key_Event (MapKey(lParam), false); + break; + + // this is complicated because Win32 seems to pack multiple mouse events into + // one update sometimes, so we always check all states and look for events + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEMOVE: + if (!in_mode_set) + { + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + IN_MouseEvent (temp); + } + break; + + // JACK: This is the mouse wheel with the Intellimouse + // Its delta is either positive or neg, and we generate the proper + // Event. + case WM_MOUSEWHEEL: + if ((short) HIWORD(wParam) > 0) { + Key_Event(K_MWHEELUP, true); + Key_Event(K_MWHEELUP, false); + } else { + Key_Event(K_MWHEELDOWN, true); + Key_Event(K_MWHEELDOWN, false); + } + break; + // KJB: Added these new palette functions + case WM_PALETTECHANGED: + if ((HWND)wParam == hWnd) + break; + /* Fall through to WM_QUERYNEWPALETTE */ + case WM_QUERYNEWPALETTE: + hdc = GetDC(NULL); + + if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + ReleaseDC(NULL,hdc); + + scr_fullupdate = 0; + + if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) + { + VID_SetPalette (vid_curpal); + InvalidateRect (mainwindow, NULL, false); + + // specifically required if WM_QUERYNEWPALETTE realizes a new palette + lRet = TRUE; + } + break; + + case WM_DISPLAYCHANGE: + if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) + { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } + break; + + case WM_CLOSE: + // this causes Close in the right-click task bar menu not to work, but right + // now bad things happen if Close is handled in that case (garbage and a + // crash on Win95) + if (!in_mode_set) + { + if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) + { + Sys_Quit (); + } + } + break; + + case MM_MCINOTIFY: + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; + } + + /* return 0 if handled message, 1 if not */ + return lRet; +} + + +extern void M_Menu_Options_f (void); +extern void M_Print (int cx, int cy, char *str); +extern void M_PrintWhite (int cx, int cy, char *str); +extern void M_DrawCharacter (int cx, int line, int num); +extern void M_DrawTransPic (int x, int y, qpic_t *pic); +extern void M_DrawPic (int x, int y, qpic_t *pic); + +static int vid_line, vid_wmodes; + +typedef struct +{ + int modenum; + char *desc; + int iscur; + int ismode13; + int width; +} modedesc_t; + +#define MAX_COLUMN_SIZE 5 +#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +static modedesc_t modedescs[MAX_MODEDESCS]; + +/* +================ +VID_MenuDraw +================ +*/ +void VID_MenuDraw (void) +{ + qpic_t *p; + char *ptr; + int lnummodes, i, j, k, column, row, dup, dupmode; + char temp[100]; + vmode_t *pv; + modedesc_t tmodedesc; + + p = Draw_CachePic ("gfx/vidmodes.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + for (i=0 ; i<3 ; i++) + { + ptr = VID_GetModeDescriptionMemCheck (i); + modedescs[i].modenum = modelist[i].modenum; + modedescs[i].desc = ptr; + modedescs[i].ismode13 = 0; + modedescs[i].iscur = 0; + + if (vid_modenum == i) + modedescs[i].iscur = 1; + } + + vid_wmodes = 3; + lnummodes = VID_NumModes (); + + for (i=3 ; iwidth != 360) || COM_CheckParm("-allow360"))) + { + dup = 0; + + for (j=3 ; jmode13; + modedescs[k].iscur = 0; + modedescs[k].width = pv->width; + + if (i == vid_modenum) + modedescs[k].iscur = 1; + + if (!dup) + vid_wmodes++; + } + } + } + } + +// sort the modes on width (to handle picking up oddball dibonly modes +// after all the others) + for (i=3 ; i<(vid_wmodes-1) ; i++) + { + for (j=(i+1) ; j modedescs[j].width) + { + tmodedesc = modedescs[i]; + modedescs[i] = modedescs[j]; + modedescs[j] = tmodedesc; + } + } + } + + + M_Print (13*8, 36, "Windowed Modes"); + + column = 16; + row = 36+2*8; + + for (i=0 ; i<3; i++) + { + if (modedescs[i].iscur) + M_PrintWhite (column, row, modedescs[i].desc); + else + M_Print (column, row, modedescs[i].desc); + + column += 13*8; + } + + if (vid_wmodes > 3) + { + M_Print (12*8, 36+4*8, "Fullscreen Modes"); + + column = 16; + row = 36+6*8; + + for (i=3 ; i= 3) + row += 3*8; + + M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); + } +} + + +/* +================ +VID_MenuKey +================ +*/ +void VID_MenuKey (int key) +{ + if (vid_testingmode) + return; + + switch (key) + { + case K_ESCAPE: + S_LocalSound ("misc/menu1.wav"); + M_Menu_Options_f (); + break; + + case K_LEFTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + + ((vid_line + 2) % VID_ROW_SIZE); + + if (vid_line >= vid_wmodes) + vid_line = vid_wmodes - 1; + break; + + case K_RIGHTARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + + ((vid_line + 4) % VID_ROW_SIZE); + + if (vid_line >= vid_wmodes) + vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; + break; + + case K_UPARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line -= VID_ROW_SIZE; + + if (vid_line < 0) + { + vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / + VID_ROW_SIZE) * VID_ROW_SIZE; + + while (vid_line >= vid_wmodes) + vid_line -= VID_ROW_SIZE; + } + break; + + case K_DOWNARROW: + S_LocalSound ("misc/menu1.wav"); + vid_line += VID_ROW_SIZE; + + if (vid_line >= vid_wmodes) + { + vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / + VID_ROW_SIZE) * VID_ROW_SIZE; + + while (vid_line < 0) + vid_line += VID_ROW_SIZE; + } + break; + + case K_ENTER: + S_LocalSound ("misc/menu1.wav"); + VID_SetMode (modedescs[vid_line].modenum, vid_curpal); + break; + + case 'T': + case 't': + S_LocalSound ("misc/menu1.wav"); + // have to set this before setting the mode because WM_PAINT + // happens during the mode set and does a VID_Update, which + // checks vid_testingmode + vid_testingmode = 1; + vid_testendtime = realtime + 5.0; + + if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) + { + vid_testingmode = 0; + } + break; + + case 'D': + case 'd': + S_LocalSound ("misc/menu1.wav"); + firstupdate = 0; + Cvar_SetValue ("_vid_default_mode_win", vid_modenum); + break; + + default: + break; + } +} diff --git a/WinQuake/vid_x.c b/WinQuake/vid_x.c index 5987b6c..a96ab17 100644 --- a/WinQuake/vid_x.c +++ b/WinQuake/vid_x.c @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // vid_x.c -- general x video driver #define _BSD diff --git a/WinQuake/view.c b/WinQuake/view.c index ececf8c..324d023 100644 --- a/WinQuake/view.c +++ b/WinQuake/view.c @@ -1,1113 +1,1113 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// view.c -- player eye positioning - -#include "quakedef.h" -#include "r_local.h" - -/* - -The view is allowed to move slightly from it's true position for bobbing, -but if it exceeds 8 pixels linear distance (spherical, not box), the list of -entities sent from the server may not include everything in the pvs, especially -when crossing a water boudnary. - -*/ - -cvar_t lcd_x = {"lcd_x","0"}; -cvar_t lcd_yaw = {"lcd_yaw","0"}; - -cvar_t scr_ofsx = {"scr_ofsx","0", false}; -cvar_t scr_ofsy = {"scr_ofsy","0", false}; -cvar_t scr_ofsz = {"scr_ofsz","0", false}; - -cvar_t cl_rollspeed = {"cl_rollspeed", "200"}; -cvar_t cl_rollangle = {"cl_rollangle", "2.0"}; - -cvar_t cl_bob = {"cl_bob","0.02", false}; -cvar_t cl_bobcycle = {"cl_bobcycle","0.6", false}; -cvar_t cl_bobup = {"cl_bobup","0.5", false}; - -cvar_t v_kicktime = {"v_kicktime", "0.5", false}; -cvar_t v_kickroll = {"v_kickroll", "0.6", false}; -cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; - -cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false}; -cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false}; -cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false}; -cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", false}; -cvar_t v_iroll_level = {"v_iroll_level", "0.1", false}; -cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", false}; - -cvar_t v_idlescale = {"v_idlescale", "0", false}; - -cvar_t crosshair = {"crosshair", "0", true}; -cvar_t cl_crossx = {"cl_crossx", "0", false}; -cvar_t cl_crossy = {"cl_crossy", "0", false}; - -cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; - -float v_dmg_time, v_dmg_roll, v_dmg_pitch; - -extern int in_forward, in_forward2, in_back; - - -/* -=============== -V_CalcRoll - -Used by view and sv_user -=============== -*/ -vec3_t forward, right, up; - -float V_CalcRoll (vec3_t angles, vec3_t velocity) -{ - float sign; - float side; - float value; - - AngleVectors (angles, forward, right, up); - side = DotProduct (velocity, right); - sign = side < 0 ? -1 : 1; - side = fabs(side); - - value = cl_rollangle.value; -// if (cl.inwater) -// value *= 6; - - if (side < cl_rollspeed.value) - side = side * value / cl_rollspeed.value; - else - side = value; - - return side*sign; - -} - - -/* -=============== -V_CalcBob - -=============== -*/ -float V_CalcBob (void) -{ - float bob; - float cycle; - - cycle = cl.time - (int)(cl.time/cl_bobcycle.value)*cl_bobcycle.value; - cycle /= cl_bobcycle.value; - if (cycle < cl_bobup.value) - cycle = M_PI * cycle / cl_bobup.value; - else - cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value); - -// bob is proportional to velocity in the xy plane -// (don't count Z, or jumping messes it up) - - bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value; -//Con_Printf ("speed: %5.1f\n", Length(cl.velocity)); - bob = bob*0.3 + bob*0.7*sin(cycle); - if (bob > 4) - bob = 4; - else if (bob < -7) - bob = -7; - return bob; - -} - - -//============================================================================= - - -cvar_t v_centermove = {"v_centermove", "0.15", false}; -cvar_t v_centerspeed = {"v_centerspeed","500"}; - - -void V_StartPitchDrift (void) -{ -#if 1 - if (cl.laststop == cl.time) - { - return; // something else is keeping it from drifting - } -#endif - if (cl.nodrift || !cl.pitchvel) - { - cl.pitchvel = v_centerspeed.value; - cl.nodrift = false; - cl.driftmove = 0; - } -} - -void V_StopPitchDrift (void) -{ - cl.laststop = cl.time; - cl.nodrift = true; - cl.pitchvel = 0; -} - -/* -=============== -V_DriftPitch - -Moves the client pitch angle towards cl.idealpitch sent by the server. - -If the user is adjusting pitch manually, either with lookup/lookdown, -mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. - -Drifting is enabled when the center view key is hit, mlook is released and -lookspring is non 0, or when -=============== -*/ -void V_DriftPitch (void) -{ - float delta, move; - - if (noclip_anglehack || !cl.onground || cls.demoplayback ) - { - cl.driftmove = 0; - cl.pitchvel = 0; - return; - } - -// don't count small mouse motion - if (cl.nodrift) - { - if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value) - cl.driftmove = 0; - else - cl.driftmove += host_frametime; - - if ( cl.driftmove > v_centermove.value) - { - V_StartPitchDrift (); - } - return; - } - - delta = cl.idealpitch - cl.viewangles[PITCH]; - - if (!delta) - { - cl.pitchvel = 0; - return; - } - - move = host_frametime * cl.pitchvel; - cl.pitchvel += host_frametime * v_centerspeed.value; - -//Con_Printf ("move: %f (%f)\n", move, host_frametime); - - if (delta > 0) - { - if (move > delta) - { - cl.pitchvel = 0; - move = delta; - } - cl.viewangles[PITCH] += move; - } - else if (delta < 0) - { - if (move > -delta) - { - cl.pitchvel = 0; - move = -delta; - } - cl.viewangles[PITCH] -= move; - } -} - - - - - -/* -============================================================================== - - PALETTE FLASHES - -============================================================================== -*/ - - -cshift_t cshift_empty = { {130,80,50}, 0 }; -cshift_t cshift_water = { {130,80,50}, 128 }; -cshift_t cshift_slime = { {0,25,5}, 150 }; -cshift_t cshift_lava = { {255,80,0}, 150 }; - -cvar_t v_gamma = {"gamma", "1", true}; - -byte gammatable[256]; // palette is sent through this - -#ifdef GLQUAKE -byte ramps[3][256]; -float v_blend[4]; // rgba 0.0 - 1.0 -#endif // GLQUAKE - -void BuildGammaTable (float g) -{ - int i, inf; - - if (g == 1.0) - { - for (i=0 ; i<256 ; i++) - gammatable[i] = i; - return; - } - - for (i=0 ; i<256 ; i++) - { - inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; - if (inf < 0) - inf = 0; - if (inf > 255) - inf = 255; - gammatable[i] = inf; - } -} - -/* -================= -V_CheckGamma -================= -*/ -qboolean V_CheckGamma (void) -{ - static float oldgammavalue; - - if (v_gamma.value == oldgammavalue) - return false; - oldgammavalue = v_gamma.value; - - BuildGammaTable (v_gamma.value); - vid.recalc_refdef = 1; // force a surface cache flush - - return true; -} - - - -/* -=============== -V_ParseDamage -=============== -*/ -void V_ParseDamage (void) -{ - int armor, blood; - vec3_t from; - int i; - vec3_t forward, right, up; - entity_t *ent; - float side; - float count; - - armor = MSG_ReadByte (); - blood = MSG_ReadByte (); - for (i=0 ; i<3 ; i++) - from[i] = MSG_ReadCoord (); - - count = blood*0.5 + armor*0.5; - if (count < 10) - count = 10; - - cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame - - cl.cshifts[CSHIFT_DAMAGE].percent += 3*count; - if (cl.cshifts[CSHIFT_DAMAGE].percent < 0) - cl.cshifts[CSHIFT_DAMAGE].percent = 0; - if (cl.cshifts[CSHIFT_DAMAGE].percent > 150) - cl.cshifts[CSHIFT_DAMAGE].percent = 150; - - if (armor > blood) - { - cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; - cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100; - cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100; - } - else if (armor) - { - cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220; - cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50; - cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50; - } - else - { - cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255; - cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0; - cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; - } - -// -// calculate view angle kicks -// - ent = &cl_entities[cl.viewentity]; - - VectorSubtract (from, ent->origin, from); - VectorNormalize (from); - - AngleVectors (ent->angles, forward, right, up); - - side = DotProduct (from, right); - v_dmg_roll = count*side*v_kickroll.value; - - side = DotProduct (from, forward); - v_dmg_pitch = count*side*v_kickpitch.value; - - v_dmg_time = v_kicktime.value; -} - - -/* -================== -V_cshift_f -================== -*/ -void V_cshift_f (void) -{ - cshift_empty.destcolor[0] = atoi(Cmd_Argv(1)); - cshift_empty.destcolor[1] = atoi(Cmd_Argv(2)); - cshift_empty.destcolor[2] = atoi(Cmd_Argv(3)); - cshift_empty.percent = atoi(Cmd_Argv(4)); -} - - -/* -================== -V_BonusFlash_f - -When you run over an item, the server sends this command -================== -*/ -void V_BonusFlash_f (void) -{ - cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; - cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; - cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; - cl.cshifts[CSHIFT_BONUS].percent = 50; -} - -/* -============= -V_SetContentsColor - -Underwater, lava, etc each has a color shift -============= -*/ -void V_SetContentsColor (int contents) -{ - switch (contents) - { - case CONTENTS_EMPTY: - case CONTENTS_SOLID: - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; - break; - case CONTENTS_LAVA: - cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; - break; - case CONTENTS_SLIME: - cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; - break; - default: - cl.cshifts[CSHIFT_CONTENTS] = cshift_water; - } -} - -/* -============= -V_CalcPowerupCshift -============= -*/ -void V_CalcPowerupCshift (void) -{ - if (cl.items & IT_QUAD) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } - else if (cl.items & IT_SUIT) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 20; - } - else if (cl.items & IT_INVISIBILITY) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; - cl.cshifts[CSHIFT_POWERUP].percent = 100; - } - else if (cl.items & IT_INVULNERABILITY) - { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } - else - cl.cshifts[CSHIFT_POWERUP].percent = 0; -} - -/* -============= -V_CalcBlend -============= -*/ -#ifdef GLQUAKE -void V_CalcBlend (void) -{ - float r, g, b, a, a2; - int j; - - r = 0; - g = 0; - b = 0; - a = 0; - - for (j=0 ; j 1) - v_blend[3] = 1; - if (v_blend[3] < 0) - v_blend[3] = 0; -} -#endif - -/* -============= -V_UpdatePalette -============= -*/ -#ifdef GLQUAKE -void V_UpdatePalette (void) -{ - int i, j; - qboolean new; - byte *basepal, *newpal; - byte pal[768]; - float r,g,b,a; - int ir, ig, ib; - qboolean force; - - V_CalcPowerupCshift (); - - new = false; - - for (i=0 ; i 255) - ir = 255; - if (ig > 255) - ig = 255; - if (ib > 255) - ib = 255; - - ramps[0][i] = gammatable[ir]; - ramps[1][i] = gammatable[ig]; - ramps[2][i] = gammatable[ib]; - } - - basepal = host_basepal; - newpal = pal; - - for (i=0 ; i<256 ; i++) - { - ir = basepal[0]; - ig = basepal[1]; - ib = basepal[2]; - basepal += 3; - - newpal[0] = ramps[0][ir]; - newpal[1] = ramps[1][ig]; - newpal[2] = ramps[2][ib]; - newpal += 3; - } - - VID_ShiftPalette (pal); -} -#else // !GLQUAKE -void V_UpdatePalette (void) -{ - int i, j; - qboolean new; - byte *basepal, *newpal; - byte pal[768]; - int r,g,b; - qboolean force; - - V_CalcPowerupCshift (); - - new = false; - - for (i=0 ; i>8; - g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8; - b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8; - } - - newpal[0] = gammatable[r]; - newpal[1] = gammatable[g]; - newpal[2] = gammatable[b]; - newpal += 3; - } - - VID_ShiftPalette (pal); -} -#endif // !GLQUAKE - - -/* -============================================================================== - - VIEW RENDERING - -============================================================================== -*/ - -float angledelta (float a) -{ - a = anglemod(a); - if (a > 180) - a -= 360; - return a; -} - -/* -================== -CalcGunAngle -================== -*/ -void CalcGunAngle (void) -{ - float yaw, pitch, move; - static float oldyaw = 0; - static float oldpitch = 0; - - yaw = r_refdef.viewangles[YAW]; - pitch = -r_refdef.viewangles[PITCH]; - - yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4; - if (yaw > 10) - yaw = 10; - if (yaw < -10) - yaw = -10; - pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4; - if (pitch > 10) - pitch = 10; - if (pitch < -10) - pitch = -10; - move = host_frametime*20; - if (yaw > oldyaw) - { - if (oldyaw + move < yaw) - yaw = oldyaw + move; - } - else - { - if (oldyaw - move > yaw) - yaw = oldyaw - move; - } - - if (pitch > oldpitch) - { - if (oldpitch + move < pitch) - pitch = oldpitch + move; - } - else - { - if (oldpitch - move > pitch) - pitch = oldpitch - move; - } - - oldyaw = yaw; - oldpitch = pitch; - - cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; - cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); - - cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; -} - -/* -============== -V_BoundOffsets -============== -*/ -void V_BoundOffsets (void) -{ - entity_t *ent; - - ent = &cl_entities[cl.viewentity]; - -// absolutely bound refresh reletive to entity clipping hull -// so the view can never be inside a solid wall - - if (r_refdef.vieworg[0] < ent->origin[0] - 14) - r_refdef.vieworg[0] = ent->origin[0] - 14; - else if (r_refdef.vieworg[0] > ent->origin[0] + 14) - r_refdef.vieworg[0] = ent->origin[0] + 14; - if (r_refdef.vieworg[1] < ent->origin[1] - 14) - r_refdef.vieworg[1] = ent->origin[1] - 14; - else if (r_refdef.vieworg[1] > ent->origin[1] + 14) - r_refdef.vieworg[1] = ent->origin[1] + 14; - if (r_refdef.vieworg[2] < ent->origin[2] - 22) - r_refdef.vieworg[2] = ent->origin[2] - 22; - else if (r_refdef.vieworg[2] > ent->origin[2] + 30) - r_refdef.vieworg[2] = ent->origin[2] + 30; -} - -/* -============== -V_AddIdle - -Idle swaying -============== -*/ -void V_AddIdle (void) -{ - r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; -} - - -/* -============== -V_CalcViewRoll - -Roll is induced by movement and damage -============== -*/ -void V_CalcViewRoll (void) -{ - float side; - - side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity); - r_refdef.viewangles[ROLL] += side; - - if (v_dmg_time > 0) - { - r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; - r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; - v_dmg_time -= host_frametime; - } - - if (cl.stats[STAT_HEALTH] <= 0) - { - r_refdef.viewangles[ROLL] = 80; // dead view angle - return; - } - -} - - -/* -================== -V_CalcIntermissionRefdef - -================== -*/ -void V_CalcIntermissionRefdef (void) -{ - entity_t *ent, *view; - float old; - -// ent is the player model (visible when out of body) - ent = &cl_entities[cl.viewentity]; -// view is the weapon model (only visible from inside body) - view = &cl.viewent; - - VectorCopy (ent->origin, r_refdef.vieworg); - VectorCopy (ent->angles, r_refdef.viewangles); - view->model = NULL; - -// allways idle in intermission - old = v_idlescale.value; - v_idlescale.value = 1; - V_AddIdle (); - v_idlescale.value = old; -} - -/* -================== -V_CalcRefdef - -================== -*/ -void V_CalcRefdef (void) -{ - entity_t *ent, *view; - int i; - vec3_t forward, right, up; - vec3_t angles; - float bob; - static float oldz = 0; - - V_DriftPitch (); - -// ent is the player model (visible when out of body) - ent = &cl_entities[cl.viewentity]; -// view is the weapon model (only visible from inside body) - view = &cl.viewent; - - -// transform the view offset by the model's matrix to get the offset from -// model origin for the view - ent->angles[YAW] = cl.viewangles[YAW]; // the model should face - // the view dir - ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face - // the view dir - - - bob = V_CalcBob (); - -// refresh position - VectorCopy (ent->origin, r_refdef.vieworg); - r_refdef.vieworg[2] += cl.viewheight + bob; - -// never let it sit exactly on a node line, because a water plane can -// dissapear when viewed with the eye exactly on it. -// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis - r_refdef.vieworg[0] += 1.0/32; - r_refdef.vieworg[1] += 1.0/32; - r_refdef.vieworg[2] += 1.0/32; - - VectorCopy (cl.viewangles, r_refdef.viewangles); - V_CalcViewRoll (); - V_AddIdle (); - -// offsets - angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are - // actually backward - angles[YAW] = ent->angles[YAW]; - angles[ROLL] = ent->angles[ROLL]; - - AngleVectors (angles, forward, right, up); - - for (i=0 ; i<3 ; i++) - r_refdef.vieworg[i] += scr_ofsx.value*forward[i] - + scr_ofsy.value*right[i] - + scr_ofsz.value*up[i]; - - - V_BoundOffsets (); - -// set up gun position - VectorCopy (cl.viewangles, view->angles); - - CalcGunAngle (); - - VectorCopy (ent->origin, view->origin); - view->origin[2] += cl.viewheight; - - for (i=0 ; i<3 ; i++) - { - view->origin[i] += forward[i]*bob*0.4; -// view->origin[i] += right[i]*bob*0.4; -// view->origin[i] += up[i]*bob*0.8; - } - view->origin[2] += bob; - -// fudge position around to keep amount of weapon visible -// roughly equal with different FOV - -#if 0 - if (cl.model_precache[cl.stats[STAT_WEAPON]] && strcmp (cl.model_precache[cl.stats[STAT_WEAPON]]->name, "progs/v_shot2.mdl")) -#endif - if (scr_viewsize.value == 110) - view->origin[2] += 1; - else if (scr_viewsize.value == 100) - view->origin[2] += 2; - else if (scr_viewsize.value == 90) - view->origin[2] += 1; - else if (scr_viewsize.value == 80) - view->origin[2] += 0.5; - - view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; - view->frame = cl.stats[STAT_WEAPONFRAME]; - view->colormap = vid.colormap; - -// set up the refresh position - VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); - -// smooth out stair step ups -if (cl.onground && ent->origin[2] - oldz > 0) -{ - float steptime; - - steptime = cl.time - cl.oldtime; - if (steptime < 0) -//FIXME I_Error ("steptime < 0"); - steptime = 0; - - oldz += steptime * 80; - if (oldz > ent->origin[2]) - oldz = ent->origin[2]; - if (ent->origin[2] - oldz > 12) - oldz = ent->origin[2] - 12; - r_refdef.vieworg[2] += oldz - ent->origin[2]; - view->origin[2] += oldz - ent->origin[2]; -} -else - oldz = ent->origin[2]; - - if (chase_active.value) - Chase_Update (); -} - -/* -================== -V_RenderView - -The player's clipping box goes from (-16 -16 -24) to (16 16 32) from -the entity origin, so any view position inside that will be valid -================== -*/ -extern vrect_t scr_vrect; - -void V_RenderView (void) -{ - if (con_forcedup) - return; - -// don't allow cheats in multiplayer - if (cl.maxclients > 1) - { - Cvar_Set ("scr_ofsx", "0"); - Cvar_Set ("scr_ofsy", "0"); - Cvar_Set ("scr_ofsz", "0"); - } - - if (cl.intermission) - { // intermission / finale rendering - V_CalcIntermissionRefdef (); - } - else - { - if (!cl.paused /* && (sv.maxclients > 1 || key_dest == key_game) */ ) - V_CalcRefdef (); - } - - R_PushDlights (); - - if (lcd_x.value) - { - // - // render two interleaved views - // - int i; - - vid.rowbytes <<= 1; - vid.aspect *= 0.5; - - r_refdef.viewangles[YAW] -= lcd_yaw.value; - for (i=0 ; i<3 ; i++) - r_refdef.vieworg[i] -= right[i]*lcd_x.value; - R_RenderView (); - - vid.buffer += vid.rowbytes>>1; - - R_PushDlights (); - - r_refdef.viewangles[YAW] += lcd_yaw.value*2; - for (i=0 ; i<3 ; i++) - r_refdef.vieworg[i] += 2*right[i]*lcd_x.value; - R_RenderView (); - - vid.buffer -= vid.rowbytes>>1; - - r_refdef.vrect.height <<= 1; - - vid.rowbytes >>= 1; - vid.aspect *= 2; - } - else - { - R_RenderView (); - } - -#ifndef GLQUAKE - if (crosshair.value) - Draw_Character (scr_vrect.x + scr_vrect.width/2 + cl_crossx.value, - scr_vrect.y + scr_vrect.height/2 + cl_crossy.value, '+'); -#endif - -} - -//============================================================================ - -/* -============= -V_Init -============= -*/ -void V_Init (void) -{ - Cmd_AddCommand ("v_cshift", V_cshift_f); - Cmd_AddCommand ("bf", V_BonusFlash_f); - Cmd_AddCommand ("centerview", V_StartPitchDrift); - - Cvar_RegisterVariable (&lcd_x); - Cvar_RegisterVariable (&lcd_yaw); - - Cvar_RegisterVariable (&v_centermove); - Cvar_RegisterVariable (&v_centerspeed); - - Cvar_RegisterVariable (&v_iyaw_cycle); - Cvar_RegisterVariable (&v_iroll_cycle); - Cvar_RegisterVariable (&v_ipitch_cycle); - Cvar_RegisterVariable (&v_iyaw_level); - Cvar_RegisterVariable (&v_iroll_level); - Cvar_RegisterVariable (&v_ipitch_level); - - Cvar_RegisterVariable (&v_idlescale); - Cvar_RegisterVariable (&crosshair); - Cvar_RegisterVariable (&cl_crossx); - Cvar_RegisterVariable (&cl_crossy); - Cvar_RegisterVariable (&gl_cshiftpercent); - - Cvar_RegisterVariable (&scr_ofsx); - Cvar_RegisterVariable (&scr_ofsy); - Cvar_RegisterVariable (&scr_ofsz); - Cvar_RegisterVariable (&cl_rollspeed); - Cvar_RegisterVariable (&cl_rollangle); - Cvar_RegisterVariable (&cl_bob); - Cvar_RegisterVariable (&cl_bobcycle); - Cvar_RegisterVariable (&cl_bobup); - - Cvar_RegisterVariable (&v_kicktime); - Cvar_RegisterVariable (&v_kickroll); - Cvar_RegisterVariable (&v_kickpitch); - - BuildGammaTable (1.0); // no gamma yet - Cvar_RegisterVariable (&v_gamma); -} - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// view.c -- player eye positioning + +#include "quakedef.h" +#include "r_local.h" + +/* + +The view is allowed to move slightly from it's true position for bobbing, +but if it exceeds 8 pixels linear distance (spherical, not box), the list of +entities sent from the server may not include everything in the pvs, especially +when crossing a water boudnary. + +*/ + +cvar_t lcd_x = {"lcd_x","0"}; +cvar_t lcd_yaw = {"lcd_yaw","0"}; + +cvar_t scr_ofsx = {"scr_ofsx","0", false}; +cvar_t scr_ofsy = {"scr_ofsy","0", false}; +cvar_t scr_ofsz = {"scr_ofsz","0", false}; + +cvar_t cl_rollspeed = {"cl_rollspeed", "200"}; +cvar_t cl_rollangle = {"cl_rollangle", "2.0"}; + +cvar_t cl_bob = {"cl_bob","0.02", false}; +cvar_t cl_bobcycle = {"cl_bobcycle","0.6", false}; +cvar_t cl_bobup = {"cl_bobup","0.5", false}; + +cvar_t v_kicktime = {"v_kicktime", "0.5", false}; +cvar_t v_kickroll = {"v_kickroll", "0.6", false}; +cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; + +cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false}; +cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false}; +cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false}; +cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", false}; +cvar_t v_iroll_level = {"v_iroll_level", "0.1", false}; +cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", false}; + +cvar_t v_idlescale = {"v_idlescale", "0", false}; + +cvar_t crosshair = {"crosshair", "0", true}; +cvar_t cl_crossx = {"cl_crossx", "0", false}; +cvar_t cl_crossy = {"cl_crossy", "0", false}; + +cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; + +float v_dmg_time, v_dmg_roll, v_dmg_pitch; + +extern int in_forward, in_forward2, in_back; + + +/* +=============== +V_CalcRoll + +Used by view and sv_user +=============== +*/ +vec3_t forward, right, up; + +float V_CalcRoll (vec3_t angles, vec3_t velocity) +{ + float sign; + float side; + float value; + + AngleVectors (angles, forward, right, up); + side = DotProduct (velocity, right); + sign = side < 0 ? -1 : 1; + side = fabs(side); + + value = cl_rollangle.value; +// if (cl.inwater) +// value *= 6; + + if (side < cl_rollspeed.value) + side = side * value / cl_rollspeed.value; + else + side = value; + + return side*sign; + +} + + +/* +=============== +V_CalcBob + +=============== +*/ +float V_CalcBob (void) +{ + float bob; + float cycle; + + cycle = cl.time - (int)(cl.time/cl_bobcycle.value)*cl_bobcycle.value; + cycle /= cl_bobcycle.value; + if (cycle < cl_bobup.value) + cycle = M_PI * cycle / cl_bobup.value; + else + cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value); + +// bob is proportional to velocity in the xy plane +// (don't count Z, or jumping messes it up) + + bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value; +//Con_Printf ("speed: %5.1f\n", Length(cl.velocity)); + bob = bob*0.3 + bob*0.7*sin(cycle); + if (bob > 4) + bob = 4; + else if (bob < -7) + bob = -7; + return bob; + +} + + +//============================================================================= + + +cvar_t v_centermove = {"v_centermove", "0.15", false}; +cvar_t v_centerspeed = {"v_centerspeed","500"}; + + +void V_StartPitchDrift (void) +{ +#if 1 + if (cl.laststop == cl.time) + { + return; // something else is keeping it from drifting + } +#endif + if (cl.nodrift || !cl.pitchvel) + { + cl.pitchvel = v_centerspeed.value; + cl.nodrift = false; + cl.driftmove = 0; + } +} + +void V_StopPitchDrift (void) +{ + cl.laststop = cl.time; + cl.nodrift = true; + cl.pitchvel = 0; +} + +/* +=============== +V_DriftPitch + +Moves the client pitch angle towards cl.idealpitch sent by the server. + +If the user is adjusting pitch manually, either with lookup/lookdown, +mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. + +Drifting is enabled when the center view key is hit, mlook is released and +lookspring is non 0, or when +=============== +*/ +void V_DriftPitch (void) +{ + float delta, move; + + if (noclip_anglehack || !cl.onground || cls.demoplayback ) + { + cl.driftmove = 0; + cl.pitchvel = 0; + return; + } + +// don't count small mouse motion + if (cl.nodrift) + { + if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value) + cl.driftmove = 0; + else + cl.driftmove += host_frametime; + + if ( cl.driftmove > v_centermove.value) + { + V_StartPitchDrift (); + } + return; + } + + delta = cl.idealpitch - cl.viewangles[PITCH]; + + if (!delta) + { + cl.pitchvel = 0; + return; + } + + move = host_frametime * cl.pitchvel; + cl.pitchvel += host_frametime * v_centerspeed.value; + +//Con_Printf ("move: %f (%f)\n", move, host_frametime); + + if (delta > 0) + { + if (move > delta) + { + cl.pitchvel = 0; + move = delta; + } + cl.viewangles[PITCH] += move; + } + else if (delta < 0) + { + if (move > -delta) + { + cl.pitchvel = 0; + move = -delta; + } + cl.viewangles[PITCH] -= move; + } +} + + + + + +/* +============================================================================== + + PALETTE FLASHES + +============================================================================== +*/ + + +cshift_t cshift_empty = { {130,80,50}, 0 }; +cshift_t cshift_water = { {130,80,50}, 128 }; +cshift_t cshift_slime = { {0,25,5}, 150 }; +cshift_t cshift_lava = { {255,80,0}, 150 }; + +cvar_t v_gamma = {"gamma", "1", true}; + +byte gammatable[256]; // palette is sent through this + +#ifdef GLQUAKE +byte ramps[3][256]; +float v_blend[4]; // rgba 0.0 - 1.0 +#endif // GLQUAKE + +void BuildGammaTable (float g) +{ + int i, inf; + + if (g == 1.0) + { + for (i=0 ; i<256 ; i++) + gammatable[i] = i; + return; + } + + for (i=0 ; i<256 ; i++) + { + inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + gammatable[i] = inf; + } +} + +/* +================= +V_CheckGamma +================= +*/ +qboolean V_CheckGamma (void) +{ + static float oldgammavalue; + + if (v_gamma.value == oldgammavalue) + return false; + oldgammavalue = v_gamma.value; + + BuildGammaTable (v_gamma.value); + vid.recalc_refdef = 1; // force a surface cache flush + + return true; +} + + + +/* +=============== +V_ParseDamage +=============== +*/ +void V_ParseDamage (void) +{ + int armor, blood; + vec3_t from; + int i; + vec3_t forward, right, up; + entity_t *ent; + float side; + float count; + + armor = MSG_ReadByte (); + blood = MSG_ReadByte (); + for (i=0 ; i<3 ; i++) + from[i] = MSG_ReadCoord (); + + count = blood*0.5 + armor*0.5; + if (count < 10) + count = 10; + + cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame + + cl.cshifts[CSHIFT_DAMAGE].percent += 3*count; + if (cl.cshifts[CSHIFT_DAMAGE].percent < 0) + cl.cshifts[CSHIFT_DAMAGE].percent = 0; + if (cl.cshifts[CSHIFT_DAMAGE].percent > 150) + cl.cshifts[CSHIFT_DAMAGE].percent = 150; + + if (armor > blood) + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100; + } + else if (armor) + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50; + } + else + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; + } + +// +// calculate view angle kicks +// + ent = &cl_entities[cl.viewentity]; + + VectorSubtract (from, ent->origin, from); + VectorNormalize (from); + + AngleVectors (ent->angles, forward, right, up); + + side = DotProduct (from, right); + v_dmg_roll = count*side*v_kickroll.value; + + side = DotProduct (from, forward); + v_dmg_pitch = count*side*v_kickpitch.value; + + v_dmg_time = v_kicktime.value; +} + + +/* +================== +V_cshift_f +================== +*/ +void V_cshift_f (void) +{ + cshift_empty.destcolor[0] = atoi(Cmd_Argv(1)); + cshift_empty.destcolor[1] = atoi(Cmd_Argv(2)); + cshift_empty.destcolor[2] = atoi(Cmd_Argv(3)); + cshift_empty.percent = atoi(Cmd_Argv(4)); +} + + +/* +================== +V_BonusFlash_f + +When you run over an item, the server sends this command +================== +*/ +void V_BonusFlash_f (void) +{ + cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; + cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; + cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; + cl.cshifts[CSHIFT_BONUS].percent = 50; +} + +/* +============= +V_SetContentsColor + +Underwater, lava, etc each has a color shift +============= +*/ +void V_SetContentsColor (int contents) +{ + switch (contents) + { + case CONTENTS_EMPTY: + case CONTENTS_SOLID: + cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + break; + case CONTENTS_LAVA: + cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; + break; + case CONTENTS_SLIME: + cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; + break; + default: + cl.cshifts[CSHIFT_CONTENTS] = cshift_water; + } +} + +/* +============= +V_CalcPowerupCshift +============= +*/ +void V_CalcPowerupCshift (void) +{ + if (cl.items & IT_QUAD) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else if (cl.items & IT_SUIT) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 20; + } + else if (cl.items & IT_INVISIBILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; + cl.cshifts[CSHIFT_POWERUP].percent = 100; + } + else if (cl.items & IT_INVULNERABILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else + cl.cshifts[CSHIFT_POWERUP].percent = 0; +} + +/* +============= +V_CalcBlend +============= +*/ +#ifdef GLQUAKE +void V_CalcBlend (void) +{ + float r, g, b, a, a2; + int j; + + r = 0; + g = 0; + b = 0; + a = 0; + + for (j=0 ; j 1) + v_blend[3] = 1; + if (v_blend[3] < 0) + v_blend[3] = 0; +} +#endif + +/* +============= +V_UpdatePalette +============= +*/ +#ifdef GLQUAKE +void V_UpdatePalette (void) +{ + int i, j; + qboolean new; + byte *basepal, *newpal; + byte pal[768]; + float r,g,b,a; + int ir, ig, ib; + qboolean force; + + V_CalcPowerupCshift (); + + new = false; + + for (i=0 ; i 255) + ir = 255; + if (ig > 255) + ig = 255; + if (ib > 255) + ib = 255; + + ramps[0][i] = gammatable[ir]; + ramps[1][i] = gammatable[ig]; + ramps[2][i] = gammatable[ib]; + } + + basepal = host_basepal; + newpal = pal; + + for (i=0 ; i<256 ; i++) + { + ir = basepal[0]; + ig = basepal[1]; + ib = basepal[2]; + basepal += 3; + + newpal[0] = ramps[0][ir]; + newpal[1] = ramps[1][ig]; + newpal[2] = ramps[2][ib]; + newpal += 3; + } + + VID_ShiftPalette (pal); +} +#else // !GLQUAKE +void V_UpdatePalette (void) +{ + int i, j; + qboolean new; + byte *basepal, *newpal; + byte pal[768]; + int r,g,b; + qboolean force; + + V_CalcPowerupCshift (); + + new = false; + + for (i=0 ; i>8; + g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8; + b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8; + } + + newpal[0] = gammatable[r]; + newpal[1] = gammatable[g]; + newpal[2] = gammatable[b]; + newpal += 3; + } + + VID_ShiftPalette (pal); +} +#endif // !GLQUAKE + + +/* +============================================================================== + + VIEW RENDERING + +============================================================================== +*/ + +float angledelta (float a) +{ + a = anglemod(a); + if (a > 180) + a -= 360; + return a; +} + +/* +================== +CalcGunAngle +================== +*/ +void CalcGunAngle (void) +{ + float yaw, pitch, move; + static float oldyaw = 0; + static float oldpitch = 0; + + yaw = r_refdef.viewangles[YAW]; + pitch = -r_refdef.viewangles[PITCH]; + + yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4; + if (yaw > 10) + yaw = 10; + if (yaw < -10) + yaw = -10; + pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4; + if (pitch > 10) + pitch = 10; + if (pitch < -10) + pitch = -10; + move = host_frametime*20; + if (yaw > oldyaw) + { + if (oldyaw + move < yaw) + yaw = oldyaw + move; + } + else + { + if (oldyaw - move > yaw) + yaw = oldyaw - move; + } + + if (pitch > oldpitch) + { + if (oldpitch + move < pitch) + pitch = oldpitch + move; + } + else + { + if (oldpitch - move > pitch) + pitch = oldpitch - move; + } + + oldyaw = yaw; + oldpitch = pitch; + + cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; + cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); + + cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; + cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; + cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; +} + +/* +============== +V_BoundOffsets +============== +*/ +void V_BoundOffsets (void) +{ + entity_t *ent; + + ent = &cl_entities[cl.viewentity]; + +// absolutely bound refresh reletive to entity clipping hull +// so the view can never be inside a solid wall + + if (r_refdef.vieworg[0] < ent->origin[0] - 14) + r_refdef.vieworg[0] = ent->origin[0] - 14; + else if (r_refdef.vieworg[0] > ent->origin[0] + 14) + r_refdef.vieworg[0] = ent->origin[0] + 14; + if (r_refdef.vieworg[1] < ent->origin[1] - 14) + r_refdef.vieworg[1] = ent->origin[1] - 14; + else if (r_refdef.vieworg[1] > ent->origin[1] + 14) + r_refdef.vieworg[1] = ent->origin[1] + 14; + if (r_refdef.vieworg[2] < ent->origin[2] - 22) + r_refdef.vieworg[2] = ent->origin[2] - 22; + else if (r_refdef.vieworg[2] > ent->origin[2] + 30) + r_refdef.vieworg[2] = ent->origin[2] + 30; +} + +/* +============== +V_AddIdle + +Idle swaying +============== +*/ +void V_AddIdle (void) +{ + r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; + r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; + r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; +} + + +/* +============== +V_CalcViewRoll + +Roll is induced by movement and damage +============== +*/ +void V_CalcViewRoll (void) +{ + float side; + + side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity); + r_refdef.viewangles[ROLL] += side; + + if (v_dmg_time > 0) + { + r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; + r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; + v_dmg_time -= host_frametime; + } + + if (cl.stats[STAT_HEALTH] <= 0) + { + r_refdef.viewangles[ROLL] = 80; // dead view angle + return; + } + +} + + +/* +================== +V_CalcIntermissionRefdef + +================== +*/ +void V_CalcIntermissionRefdef (void) +{ + entity_t *ent, *view; + float old; + +// ent is the player model (visible when out of body) + ent = &cl_entities[cl.viewentity]; +// view is the weapon model (only visible from inside body) + view = &cl.viewent; + + VectorCopy (ent->origin, r_refdef.vieworg); + VectorCopy (ent->angles, r_refdef.viewangles); + view->model = NULL; + +// allways idle in intermission + old = v_idlescale.value; + v_idlescale.value = 1; + V_AddIdle (); + v_idlescale.value = old; +} + +/* +================== +V_CalcRefdef + +================== +*/ +void V_CalcRefdef (void) +{ + entity_t *ent, *view; + int i; + vec3_t forward, right, up; + vec3_t angles; + float bob; + static float oldz = 0; + + V_DriftPitch (); + +// ent is the player model (visible when out of body) + ent = &cl_entities[cl.viewentity]; +// view is the weapon model (only visible from inside body) + view = &cl.viewent; + + +// transform the view offset by the model's matrix to get the offset from +// model origin for the view + ent->angles[YAW] = cl.viewangles[YAW]; // the model should face + // the view dir + ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face + // the view dir + + + bob = V_CalcBob (); + +// refresh position + VectorCopy (ent->origin, r_refdef.vieworg); + r_refdef.vieworg[2] += cl.viewheight + bob; + +// never let it sit exactly on a node line, because a water plane can +// dissapear when viewed with the eye exactly on it. +// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis + r_refdef.vieworg[0] += 1.0/32; + r_refdef.vieworg[1] += 1.0/32; + r_refdef.vieworg[2] += 1.0/32; + + VectorCopy (cl.viewangles, r_refdef.viewangles); + V_CalcViewRoll (); + V_AddIdle (); + +// offsets + angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are + // actually backward + angles[YAW] = ent->angles[YAW]; + angles[ROLL] = ent->angles[ROLL]; + + AngleVectors (angles, forward, right, up); + + for (i=0 ; i<3 ; i++) + r_refdef.vieworg[i] += scr_ofsx.value*forward[i] + + scr_ofsy.value*right[i] + + scr_ofsz.value*up[i]; + + + V_BoundOffsets (); + +// set up gun position + VectorCopy (cl.viewangles, view->angles); + + CalcGunAngle (); + + VectorCopy (ent->origin, view->origin); + view->origin[2] += cl.viewheight; + + for (i=0 ; i<3 ; i++) + { + view->origin[i] += forward[i]*bob*0.4; +// view->origin[i] += right[i]*bob*0.4; +// view->origin[i] += up[i]*bob*0.8; + } + view->origin[2] += bob; + +// fudge position around to keep amount of weapon visible +// roughly equal with different FOV + +#if 0 + if (cl.model_precache[cl.stats[STAT_WEAPON]] && strcmp (cl.model_precache[cl.stats[STAT_WEAPON]]->name, "progs/v_shot2.mdl")) +#endif + if (scr_viewsize.value == 110) + view->origin[2] += 1; + else if (scr_viewsize.value == 100) + view->origin[2] += 2; + else if (scr_viewsize.value == 90) + view->origin[2] += 1; + else if (scr_viewsize.value == 80) + view->origin[2] += 0.5; + + view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; + view->frame = cl.stats[STAT_WEAPONFRAME]; + view->colormap = vid.colormap; + +// set up the refresh position + VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); + +// smooth out stair step ups +if (cl.onground && ent->origin[2] - oldz > 0) +{ + float steptime; + + steptime = cl.time - cl.oldtime; + if (steptime < 0) +//FIXME I_Error ("steptime < 0"); + steptime = 0; + + oldz += steptime * 80; + if (oldz > ent->origin[2]) + oldz = ent->origin[2]; + if (ent->origin[2] - oldz > 12) + oldz = ent->origin[2] - 12; + r_refdef.vieworg[2] += oldz - ent->origin[2]; + view->origin[2] += oldz - ent->origin[2]; +} +else + oldz = ent->origin[2]; + + if (chase_active.value) + Chase_Update (); +} + +/* +================== +V_RenderView + +The player's clipping box goes from (-16 -16 -24) to (16 16 32) from +the entity origin, so any view position inside that will be valid +================== +*/ +extern vrect_t scr_vrect; + +void V_RenderView (void) +{ + if (con_forcedup) + return; + +// don't allow cheats in multiplayer + if (cl.maxclients > 1) + { + Cvar_Set ("scr_ofsx", "0"); + Cvar_Set ("scr_ofsy", "0"); + Cvar_Set ("scr_ofsz", "0"); + } + + if (cl.intermission) + { // intermission / finale rendering + V_CalcIntermissionRefdef (); + } + else + { + if (!cl.paused /* && (sv.maxclients > 1 || key_dest == key_game) */ ) + V_CalcRefdef (); + } + + R_PushDlights (); + + if (lcd_x.value) + { + // + // render two interleaved views + // + int i; + + vid.rowbytes <<= 1; + vid.aspect *= 0.5; + + r_refdef.viewangles[YAW] -= lcd_yaw.value; + for (i=0 ; i<3 ; i++) + r_refdef.vieworg[i] -= right[i]*lcd_x.value; + R_RenderView (); + + vid.buffer += vid.rowbytes>>1; + + R_PushDlights (); + + r_refdef.viewangles[YAW] += lcd_yaw.value*2; + for (i=0 ; i<3 ; i++) + r_refdef.vieworg[i] += 2*right[i]*lcd_x.value; + R_RenderView (); + + vid.buffer -= vid.rowbytes>>1; + + r_refdef.vrect.height <<= 1; + + vid.rowbytes >>= 1; + vid.aspect *= 2; + } + else + { + R_RenderView (); + } + +#ifndef GLQUAKE + if (crosshair.value) + Draw_Character (scr_vrect.x + scr_vrect.width/2 + cl_crossx.value, + scr_vrect.y + scr_vrect.height/2 + cl_crossy.value, '+'); +#endif + +} + +//============================================================================ + +/* +============= +V_Init +============= +*/ +void V_Init (void) +{ + Cmd_AddCommand ("v_cshift", V_cshift_f); + Cmd_AddCommand ("bf", V_BonusFlash_f); + Cmd_AddCommand ("centerview", V_StartPitchDrift); + + Cvar_RegisterVariable (&lcd_x); + Cvar_RegisterVariable (&lcd_yaw); + + Cvar_RegisterVariable (&v_centermove); + Cvar_RegisterVariable (&v_centerspeed); + + Cvar_RegisterVariable (&v_iyaw_cycle); + Cvar_RegisterVariable (&v_iroll_cycle); + Cvar_RegisterVariable (&v_ipitch_cycle); + Cvar_RegisterVariable (&v_iyaw_level); + Cvar_RegisterVariable (&v_iroll_level); + Cvar_RegisterVariable (&v_ipitch_level); + + Cvar_RegisterVariable (&v_idlescale); + Cvar_RegisterVariable (&crosshair); + Cvar_RegisterVariable (&cl_crossx); + Cvar_RegisterVariable (&cl_crossy); + Cvar_RegisterVariable (&gl_cshiftpercent); + + Cvar_RegisterVariable (&scr_ofsx); + Cvar_RegisterVariable (&scr_ofsy); + Cvar_RegisterVariable (&scr_ofsz); + Cvar_RegisterVariable (&cl_rollspeed); + Cvar_RegisterVariable (&cl_rollangle); + Cvar_RegisterVariable (&cl_bob); + Cvar_RegisterVariable (&cl_bobcycle); + Cvar_RegisterVariable (&cl_bobup); + + Cvar_RegisterVariable (&v_kicktime); + Cvar_RegisterVariable (&v_kickroll); + Cvar_RegisterVariable (&v_kickpitch); + + BuildGammaTable (1.0); // no gamma yet + Cvar_RegisterVariable (&v_gamma); +} + + diff --git a/WinQuake/view.h b/WinQuake/view.h index 82123a1..63db3cd 100644 --- a/WinQuake/view.h +++ b/WinQuake/view.h @@ -1,35 +1,35 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// view.h - -extern cvar_t v_gamma; - -extern byte gammatable[256]; // palette is sent through this -extern byte ramps[3][256]; -extern float v_blend[4]; - -extern cvar_t lcd_x; - - -void V_Init (void); -void V_RenderView (void); -float V_CalcRoll (vec3_t angles, vec3_t velocity); -void V_UpdatePalette (void); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// view.h + +extern cvar_t v_gamma; + +extern byte gammatable[256]; // palette is sent through this +extern byte ramps[3][256]; +extern float v_blend[4]; + +extern cvar_t lcd_x; + + +void V_Init (void); +void V_RenderView (void); +float V_CalcRoll (vec3_t angles, vec3_t velocity); +void V_UpdatePalette (void); + diff --git a/WinQuake/vregset.c b/WinQuake/vregset.c index ce009c8..6b3495a 100644 --- a/WinQuake/vregset.c +++ b/WinQuake/vregset.c @@ -1,81 +1,81 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// vregset.c: video register-setting interpreter -// - -#include -#include - -#include "quakedef.h" -#include "vregset.h" - -//#define outportb loutportb - -void loutportb (int port, int val) -{ - printf ("port, val: %x %x\n", port, val); - getch (); -} - -/* -================ -VideoRegisterSet -================ -*/ -void VideoRegisterSet (int *pregset) -{ - int port, temp0, temp1, temp2; - - for ( ;; ) - { - switch (*pregset++) - { - case VRS_END: - return; - - case VRS_BYTE_OUT: - port = *pregset++; - outportb (port, *pregset++); - break; - - case VRS_BYTE_RMW: - port = *pregset++; - temp0 = *pregset++; - temp1 = *pregset++; - temp2 = inportb (port); - temp2 &= temp0; - temp2 |= temp1; - outportb (port, temp2); - break; - - case VRS_WORD_OUT: - port = *pregset++; - outportb (port, *pregset & 0xFF); - outportb (port+1, *pregset >> 8); - pregset++; - break; - - default: - Sys_Error ("VideoRegisterSet: Invalid command\n"); - } - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// vregset.c: video register-setting interpreter +// + +#include +#include + +#include "quakedef.h" +#include "vregset.h" + +//#define outportb loutportb + +void loutportb (int port, int val) +{ + printf ("port, val: %x %x\n", port, val); + getch (); +} + +/* +================ +VideoRegisterSet +================ +*/ +void VideoRegisterSet (int *pregset) +{ + int port, temp0, temp1, temp2; + + for ( ;; ) + { + switch (*pregset++) + { + case VRS_END: + return; + + case VRS_BYTE_OUT: + port = *pregset++; + outportb (port, *pregset++); + break; + + case VRS_BYTE_RMW: + port = *pregset++; + temp0 = *pregset++; + temp1 = *pregset++; + temp2 = inportb (port); + temp2 &= temp0; + temp2 |= temp1; + outportb (port, temp2); + break; + + case VRS_WORD_OUT: + port = *pregset++; + outportb (port, *pregset & 0xFF); + outportb (port+1, *pregset >> 8); + pregset++; + break; + + default: + Sys_Error ("VideoRegisterSet: Invalid command\n"); + } + } +} + diff --git a/WinQuake/vregset.h b/WinQuake/vregset.h index 822c76c..4d15401 100644 --- a/WinQuake/vregset.h +++ b/WinQuake/vregset.h @@ -1,56 +1,56 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// -// vregset.h: header file for video register-setting interpreter -// - -// -// registers & subregisters -// -#define MISC_OUTPUT 0x3C2 - -#define SC_INDEX 0x3C4 -#define SC_DATA 0x3C5 -#define SYNC_RESET 0 -#define MAP_MASK 2 -#define MEMORY_MODE 4 - -#define GC_INDEX 0x3CE -#define GC_DATA 0x3CF -#define READ_MAP 4 -#define GRAPHICS_MODE 5 -#define MISCELLANOUS 6 - -#define CRTC_INDEX 0x3D4 -#define CRTC_DATA 0x3D5 -#define MAX_SCAN_LINE 9 -#define UNDERLINE 0x14 -#define MODE_CONTROL 0x17 - -// -// register-set commands -// -#define VRS_END 0 -#define VRS_BYTE_OUT 1 -#define VRS_BYTE_RMW 2 -#define VRS_WORD_OUT 3 - -void VideoRegisterSet (int *pregset); - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// vregset.h: header file for video register-setting interpreter +// + +// +// registers & subregisters +// +#define MISC_OUTPUT 0x3C2 + +#define SC_INDEX 0x3C4 +#define SC_DATA 0x3C5 +#define SYNC_RESET 0 +#define MAP_MASK 2 +#define MEMORY_MODE 4 + +#define GC_INDEX 0x3CE +#define GC_DATA 0x3CF +#define READ_MAP 4 +#define GRAPHICS_MODE 5 +#define MISCELLANOUS 6 + +#define CRTC_INDEX 0x3D4 +#define CRTC_DATA 0x3D5 +#define MAX_SCAN_LINE 9 +#define UNDERLINE 0x14 +#define MODE_CONTROL 0x17 + +// +// register-set commands +// +#define VRS_END 0 +#define VRS_BYTE_OUT 1 +#define VRS_BYTE_RMW 2 +#define VRS_WORD_OUT 3 + +void VideoRegisterSet (int *pregset); + diff --git a/WinQuake/wad.c b/WinQuake/wad.c index c84f72c..1eb8b59 100644 --- a/WinQuake/wad.c +++ b/WinQuake/wad.c @@ -1,158 +1,158 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// wad.c - -#include "quakedef.h" - -int wad_numlumps; -lumpinfo_t *wad_lumps; -byte *wad_base; - -void SwapPic (qpic_t *pic); - -/* -================== -W_CleanupName - -Lowercases name and pads with spaces and a terminating 0 to the length of -lumpinfo_t->name. -Used so lumpname lookups can proceed rapidly by comparing 4 chars at a time -Space padding is so names can be printed nicely in tables. -Can safely be performed in place. -================== -*/ -void W_CleanupName (char *in, char *out) -{ - int i; - int c; - - for (i=0 ; i<16 ; i++ ) - { - c = in[i]; - if (!c) - break; - - if (c >= 'A' && c <= 'Z') - c += ('a' - 'A'); - out[i] = c; - } - - for ( ; i< 16 ; i++ ) - out[i] = 0; -} - - - -/* -==================== -W_LoadWadFile -==================== -*/ -void W_LoadWadFile (char *filename) -{ - lumpinfo_t *lump_p; - wadinfo_t *header; - unsigned i; - int infotableofs; - - wad_base = COM_LoadHunkFile (filename); - if (!wad_base) - Sys_Error ("W_LoadWadFile: couldn't load %s", filename); - - header = (wadinfo_t *)wad_base; - - if (header->identification[0] != 'W' - || header->identification[1] != 'A' - || header->identification[2] != 'D' - || header->identification[3] != '2') - Sys_Error ("Wad file %s doesn't have WAD2 id\n",filename); - - wad_numlumps = LittleLong(header->numlumps); - infotableofs = LittleLong(header->infotableofs); - wad_lumps = (lumpinfo_t *)(wad_base + infotableofs); - - for (i=0, lump_p = wad_lumps ; ifilepos = LittleLong(lump_p->filepos); - lump_p->size = LittleLong(lump_p->size); - W_CleanupName (lump_p->name, lump_p->name); - if (lump_p->type == TYP_QPIC) - SwapPic ( (qpic_t *)(wad_base + lump_p->filepos)); - } -} - - -/* -============= -W_GetLumpinfo -============= -*/ -lumpinfo_t *W_GetLumpinfo (char *name) -{ - int i; - lumpinfo_t *lump_p; - char clean[16]; - - W_CleanupName (name, clean); - - for (lump_p=wad_lumps, i=0 ; iname)) - return lump_p; - } - - Sys_Error ("W_GetLumpinfo: %s not found", name); - return NULL; -} - -void *W_GetLumpName (char *name) -{ - lumpinfo_t *lump; - - lump = W_GetLumpinfo (name); - - return (void *)(wad_base + lump->filepos); -} - -void *W_GetLumpNum (int num) -{ - lumpinfo_t *lump; - - if (num < 0 || num > wad_numlumps) - Sys_Error ("W_GetLumpNum: bad number: %i", num); - - lump = wad_lumps + num; - - return (void *)(wad_base + lump->filepos); -} - -/* -============================================================================= - -automatic byte swapping - -============================================================================= -*/ - -void SwapPic (qpic_t *pic) -{ - pic->width = LittleLong(pic->width); - pic->height = LittleLong(pic->height); -} +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// wad.c + +#include "quakedef.h" + +int wad_numlumps; +lumpinfo_t *wad_lumps; +byte *wad_base; + +void SwapPic (qpic_t *pic); + +/* +================== +W_CleanupName + +Lowercases name and pads with spaces and a terminating 0 to the length of +lumpinfo_t->name. +Used so lumpname lookups can proceed rapidly by comparing 4 chars at a time +Space padding is so names can be printed nicely in tables. +Can safely be performed in place. +================== +*/ +void W_CleanupName (char *in, char *out) +{ + int i; + int c; + + for (i=0 ; i<16 ; i++ ) + { + c = in[i]; + if (!c) + break; + + if (c >= 'A' && c <= 'Z') + c += ('a' - 'A'); + out[i] = c; + } + + for ( ; i< 16 ; i++ ) + out[i] = 0; +} + + + +/* +==================== +W_LoadWadFile +==================== +*/ +void W_LoadWadFile (char *filename) +{ + lumpinfo_t *lump_p; + wadinfo_t *header; + unsigned i; + int infotableofs; + + wad_base = COM_LoadHunkFile (filename); + if (!wad_base) + Sys_Error ("W_LoadWadFile: couldn't load %s", filename); + + header = (wadinfo_t *)wad_base; + + if (header->identification[0] != 'W' + || header->identification[1] != 'A' + || header->identification[2] != 'D' + || header->identification[3] != '2') + Sys_Error ("Wad file %s doesn't have WAD2 id\n",filename); + + wad_numlumps = LittleLong(header->numlumps); + infotableofs = LittleLong(header->infotableofs); + wad_lumps = (lumpinfo_t *)(wad_base + infotableofs); + + for (i=0, lump_p = wad_lumps ; ifilepos = LittleLong(lump_p->filepos); + lump_p->size = LittleLong(lump_p->size); + W_CleanupName (lump_p->name, lump_p->name); + if (lump_p->type == TYP_QPIC) + SwapPic ( (qpic_t *)(wad_base + lump_p->filepos)); + } +} + + +/* +============= +W_GetLumpinfo +============= +*/ +lumpinfo_t *W_GetLumpinfo (char *name) +{ + int i; + lumpinfo_t *lump_p; + char clean[16]; + + W_CleanupName (name, clean); + + for (lump_p=wad_lumps, i=0 ; iname)) + return lump_p; + } + + Sys_Error ("W_GetLumpinfo: %s not found", name); + return NULL; +} + +void *W_GetLumpName (char *name) +{ + lumpinfo_t *lump; + + lump = W_GetLumpinfo (name); + + return (void *)(wad_base + lump->filepos); +} + +void *W_GetLumpNum (int num) +{ + lumpinfo_t *lump; + + if (num < 0 || num > wad_numlumps) + Sys_Error ("W_GetLumpNum: bad number: %i", num); + + lump = wad_lumps + num; + + return (void *)(wad_base + lump->filepos); +} + +/* +============================================================================= + +automatic byte swapping + +============================================================================= +*/ + +void SwapPic (qpic_t *pic) +{ + pic->width = LittleLong(pic->width); + pic->height = LittleLong(pic->height); +} diff --git a/WinQuake/wad.h b/WinQuake/wad.h index 9a740d9..125f5d7 100644 --- a/WinQuake/wad.h +++ b/WinQuake/wad.h @@ -1,75 +1,75 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// wad.h - -//=============== -// TYPES -//=============== - -#define CMP_NONE 0 -#define CMP_LZSS 1 - -#define TYP_NONE 0 -#define TYP_LABEL 1 - -#define TYP_LUMPY 64 // 64 + grab command number -#define TYP_PALETTE 64 -#define TYP_QTEX 65 -#define TYP_QPIC 66 -#define TYP_SOUND 67 -#define TYP_MIPTEX 68 - -typedef struct -{ - int width, height; - byte data[4]; // variably sized -} qpic_t; - - - -typedef struct -{ - char identification[4]; // should be WAD2 or 2DAW - int numlumps; - int infotableofs; -} wadinfo_t; - -typedef struct -{ - int filepos; - int disksize; - int size; // uncompressed - char type; - char compression; - char pad1, pad2; - char name[16]; // must be null terminated -} lumpinfo_t; - -extern int wad_numlumps; -extern lumpinfo_t *wad_lumps; -extern byte *wad_base; - -void W_LoadWadFile (char *filename); -void W_CleanupName (char *in, char *out); -lumpinfo_t *W_GetLumpinfo (char *name); -void *W_GetLumpName (char *name); -void *W_GetLumpNum (int num); - -void SwapPic (qpic_t *pic); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// wad.h + +//=============== +// TYPES +//=============== + +#define CMP_NONE 0 +#define CMP_LZSS 1 + +#define TYP_NONE 0 +#define TYP_LABEL 1 + +#define TYP_LUMPY 64 // 64 + grab command number +#define TYP_PALETTE 64 +#define TYP_QTEX 65 +#define TYP_QPIC 66 +#define TYP_SOUND 67 +#define TYP_MIPTEX 68 + +typedef struct +{ + int width, height; + byte data[4]; // variably sized +} qpic_t; + + + +typedef struct +{ + char identification[4]; // should be WAD2 or 2DAW + int numlumps; + int infotableofs; +} wadinfo_t; + +typedef struct +{ + int filepos; + int disksize; + int size; // uncompressed + char type; + char compression; + char pad1, pad2; + char name[16]; // must be null terminated +} lumpinfo_t; + +extern int wad_numlumps; +extern lumpinfo_t *wad_lumps; +extern byte *wad_base; + +void W_LoadWadFile (char *filename); +void W_CleanupName (char *in, char *out); +lumpinfo_t *W_GetLumpinfo (char *name); +void *W_GetLumpName (char *name); +void *W_GetLumpNum (int num); + +void SwapPic (qpic_t *pic); diff --git a/WinQuake/winquake.h b/WinQuake/winquake.h index 57bc779..04c03d1 100644 --- a/WinQuake/winquake.h +++ b/WinQuake/winquake.h @@ -1,114 +1,114 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// winquake.h: Win32-specific Quake header file - -#pragma warning( disable : 4229 ) // mgraph gets this - -#include -#define WM_MOUSEWHEEL 0x020A - -#ifndef SERVERONLY -#include -#include -#ifndef GLQUAKE -#include -#endif -#endif - -extern HINSTANCE global_hInstance; -extern int global_nCmdShow; - -#ifndef SERVERONLY - -extern LPDIRECTDRAW lpDD; -extern qboolean DDActive; -extern LPDIRECTDRAWSURFACE lpPrimary; -extern LPDIRECTDRAWSURFACE lpFrontBuffer; -extern LPDIRECTDRAWSURFACE lpBackBuffer; -extern LPDIRECTDRAWPALETTE lpDDPal; -extern LPDIRECTSOUND pDS; -extern LPDIRECTSOUNDBUFFER pDSBuf; - -extern DWORD gSndBufSize; -//#define SNDBUFSIZE 65536 - -void VID_LockBuffer (void); -void VID_UnlockBuffer (void); - -#endif - -typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; - -extern modestate_t modestate; - -extern HWND mainwindow; -extern qboolean ActiveApp, Minimized; - -extern qboolean WinNT; - -int VID_ForceUnlockedAndReturnState (void); -void VID_ForceLockState (int lk); - -void IN_ShowMouse (void); -void IN_DeactivateMouse (void); -void IN_HideMouse (void); -void IN_ActivateMouse (void); -void IN_RestoreOriginalMouseState (void); -void IN_SetQuakeMouseState (void); -void IN_MouseEvent (int mstate); - -extern qboolean winsock_lib_initialized; - -extern cvar_t _windowed_mouse; - -extern int window_center_x, window_center_y; -extern RECT window_rect; - -extern qboolean mouseinitialized; -extern HWND hwnd_dialog; - -extern HANDLE hinput, houtput; - -void IN_UpdateClipCursor (void); -void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify); - -void S_BlockSound (void); -void S_UnblockSound (void); - -void VID_SetDefaultMode (void); - -int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); -int (PASCAL FAR *pWSACleanup)(void); -int (PASCAL FAR *pWSAGetLastError)(void); -SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); -int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); -int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, - const char FAR * optval, int optlen); -int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, - struct sockaddr FAR *from, int FAR * fromlen); -int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, - const struct sockaddr FAR *to, int tolen); -int (PASCAL FAR *pclosesocket)(SOCKET s); -int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); -struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); -struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, - int len, int type); -int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, - int FAR * namelen); +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// winquake.h: Win32-specific Quake header file + +#pragma warning( disable : 4229 ) // mgraph gets this + +#include +#define WM_MOUSEWHEEL 0x020A + +#ifndef SERVERONLY +#include +#include +#ifndef GLQUAKE +#include +#endif +#endif + +extern HINSTANCE global_hInstance; +extern int global_nCmdShow; + +#ifndef SERVERONLY + +extern LPDIRECTDRAW lpDD; +extern qboolean DDActive; +extern LPDIRECTDRAWSURFACE lpPrimary; +extern LPDIRECTDRAWSURFACE lpFrontBuffer; +extern LPDIRECTDRAWSURFACE lpBackBuffer; +extern LPDIRECTDRAWPALETTE lpDDPal; +extern LPDIRECTSOUND pDS; +extern LPDIRECTSOUNDBUFFER pDSBuf; + +extern DWORD gSndBufSize; +//#define SNDBUFSIZE 65536 + +void VID_LockBuffer (void); +void VID_UnlockBuffer (void); + +#endif + +typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; + +extern modestate_t modestate; + +extern HWND mainwindow; +extern qboolean ActiveApp, Minimized; + +extern qboolean WinNT; + +int VID_ForceUnlockedAndReturnState (void); +void VID_ForceLockState (int lk); + +void IN_ShowMouse (void); +void IN_DeactivateMouse (void); +void IN_HideMouse (void); +void IN_ActivateMouse (void); +void IN_RestoreOriginalMouseState (void); +void IN_SetQuakeMouseState (void); +void IN_MouseEvent (int mstate); + +extern qboolean winsock_lib_initialized; + +extern cvar_t _windowed_mouse; + +extern int window_center_x, window_center_y; +extern RECT window_rect; + +extern qboolean mouseinitialized; +extern HWND hwnd_dialog; + +extern HANDLE hinput, houtput; + +void IN_UpdateClipCursor (void); +void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify); + +void S_BlockSound (void); +void S_UnblockSound (void); + +void VID_SetDefaultMode (void); + +int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); +int (PASCAL FAR *pWSACleanup)(void); +int (PASCAL FAR *pWSAGetLastError)(void); +SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); +int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); +int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, + const char FAR * optval, int optlen); +int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, + struct sockaddr FAR *from, int FAR * fromlen); +int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, + const struct sockaddr FAR *to, int tolen); +int (PASCAL FAR *pclosesocket)(SOCKET s); +int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); +struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); +struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, + int len, int type); +int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, + int FAR * namelen); diff --git a/WinQuake/winquake.rc b/WinQuake/winquake.rc index 5fb0a24..9519e6b 100644 --- a/WinQuake/winquake.rc +++ b/WinQuake/winquake.rc @@ -1,131 +1,131 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON2 ICON DISCARDABLE "quake.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_DIALOG1 DIALOGEX 0, 0, 62, 21 -STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP -EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE -FONT 16, "Times New Roman", 0, 0, 0x1 -BEGIN - CTEXT "Starting Quake...",IDC_STATIC,4,6,54,8 -END - -IDD_PROGRESS DIALOGEX 0, 0, 333, 45 -STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | - WS_VISIBLE -EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Creating 15 bit inverse palette. This is only done once, so just be patient for the next 30-60 seconds.", - IDC_STATIC,7,19,319,10 - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,29, - 319,11 - LTEXT "Starting Quake...",IDC_STATIC,7,4,54,8 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_DIALOG1, DIALOG - BEGIN - LEFTMARGIN, 4 - RIGHTMARGIN, 58 - TOPMARGIN, 6 - BOTTOMMARGIN, 16 - HORZGUIDE, 6 - HORZGUIDE, 16 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_STRING1 "WinQuake" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON2 ICON DISCARDABLE "quake.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 0, 0, 62, 21 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP +EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE +FONT 16, "Times New Roman", 0, 0, 0x1 +BEGIN + CTEXT "Starting Quake...",IDC_STATIC,4,6,54,8 +END + +IDD_PROGRESS DIALOGEX 0, 0, 333, 45 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | + WS_VISIBLE +EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Creating 15 bit inverse palette. This is only done once, so just be patient for the next 30-60 seconds.", + IDC_STATIC,7,19,319,10 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",0x0,7,29, + 319,11 + LTEXT "Starting Quake...",IDC_STATIC,7,4,54,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 58 + TOPMARGIN, 6 + BOTTOMMARGIN, 16 + HORZGUIDE, 6 + HORZGUIDE, 16 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_STRING1 "WinQuake" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/WinQuake/world.c b/WinQuake/world.c index e1acfea..ccb7cd8 100644 --- a/WinQuake/world.c +++ b/WinQuake/world.c @@ -1,962 +1,962 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// world.c -- world query functions - -#include "quakedef.h" - -/* - -entities never clip against themselves, or their owner - -line of sight checks trace->crosscontent, but bullets don't - -*/ - - -typedef struct -{ - vec3_t boxmins, boxmaxs;// enclose the test object along entire move - float *mins, *maxs; // size of the moving object - vec3_t mins2, maxs2; // size when clipping against mosnters - float *start, *end; - trace_t trace; - int type; - edict_t *passedict; -} moveclip_t; - - -int SV_HullPointContents (hull_t *hull, int num, vec3_t p); - -/* -=============================================================================== - -HULL BOXES - -=============================================================================== -*/ - - -static hull_t box_hull; -static dclipnode_t box_clipnodes[6]; -static mplane_t box_planes[6]; - -/* -=================== -SV_InitBoxHull - -Set up the planes and clipnodes so that the six floats of a bounding box -can just be stored out and get a proper hull_t structure. -=================== -*/ -void SV_InitBoxHull (void) -{ - int i; - int side; - - box_hull.clipnodes = box_clipnodes; - box_hull.planes = box_planes; - box_hull.firstclipnode = 0; - box_hull.lastclipnode = 5; - - for (i=0 ; i<6 ; i++) - { - box_clipnodes[i].planenum = i; - - side = i&1; - - box_clipnodes[i].children[side] = CONTENTS_EMPTY; - if (i != 5) - box_clipnodes[i].children[side^1] = i + 1; - else - box_clipnodes[i].children[side^1] = CONTENTS_SOLID; - - box_planes[i].type = i>>1; - box_planes[i].normal[i>>1] = 1; - } - -} - - -/* -=================== -SV_HullForBox - -To keep everything totally uniform, bounding boxes are turned into small -BSP trees instead of being compared directly. -=================== -*/ -hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs) -{ - box_planes[0].dist = maxs[0]; - box_planes[1].dist = mins[0]; - box_planes[2].dist = maxs[1]; - box_planes[3].dist = mins[1]; - box_planes[4].dist = maxs[2]; - box_planes[5].dist = mins[2]; - - return &box_hull; -} - - - -/* -================ -SV_HullForEntity - -Returns a hull that can be used for testing or clipping an object of mins/maxs -size. -Offset is filled in to contain the adjustment that must be added to the -testing object's origin to get a point to use with the returned hull. -================ -*/ -hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) -{ - model_t *model; - vec3_t size; - vec3_t hullmins, hullmaxs; - hull_t *hull; - -// decide which clipping hull to use, based on the size - if (ent->v.solid == SOLID_BSP) - { // explicit hulls in the BSP model - if (ent->v.movetype != MOVETYPE_PUSH) - Sys_Error ("SOLID_BSP without MOVETYPE_PUSH"); - - model = sv.models[ (int)ent->v.modelindex ]; - - if (!model || model->type != mod_brush) - Sys_Error ("MOVETYPE_PUSH with a non bsp model"); - - VectorSubtract (maxs, mins, size); - if (size[0] < 3) - hull = &model->hulls[0]; - else if (size[0] <= 32) - hull = &model->hulls[1]; - else - hull = &model->hulls[2]; - -// calculate an offset value to center the origin - VectorSubtract (hull->clip_mins, mins, offset); - VectorAdd (offset, ent->v.origin, offset); - } - else - { // create a temp hull from bounding box sizes - - VectorSubtract (ent->v.mins, maxs, hullmins); - VectorSubtract (ent->v.maxs, mins, hullmaxs); - hull = SV_HullForBox (hullmins, hullmaxs); - - VectorCopy (ent->v.origin, offset); - } - - - return hull; -} - -/* -=============================================================================== - -ENTITY AREA CHECKING - -=============================================================================== -*/ - -typedef struct areanode_s -{ - int axis; // -1 = leaf node - float dist; - struct areanode_s *children[2]; - link_t trigger_edicts; - link_t solid_edicts; -} areanode_t; - -#define AREA_DEPTH 4 -#define AREA_NODES 32 - -static areanode_t sv_areanodes[AREA_NODES]; -static int sv_numareanodes; - -/* -=============== -SV_CreateAreaNode - -=============== -*/ -areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) -{ - areanode_t *anode; - vec3_t size; - vec3_t mins1, maxs1, mins2, maxs2; - - anode = &sv_areanodes[sv_numareanodes]; - sv_numareanodes++; - - ClearLink (&anode->trigger_edicts); - ClearLink (&anode->solid_edicts); - - if (depth == AREA_DEPTH) - { - anode->axis = -1; - anode->children[0] = anode->children[1] = NULL; - return anode; - } - - VectorSubtract (maxs, mins, size); - if (size[0] > size[1]) - anode->axis = 0; - else - anode->axis = 1; - - anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); - VectorCopy (mins, mins1); - VectorCopy (mins, mins2); - VectorCopy (maxs, maxs1); - VectorCopy (maxs, maxs2); - - maxs1[anode->axis] = mins2[anode->axis] = anode->dist; - - anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2); - anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1); - - return anode; -} - -/* -=============== -SV_ClearWorld - -=============== -*/ -void SV_ClearWorld (void) -{ - SV_InitBoxHull (); - - memset (sv_areanodes, 0, sizeof(sv_areanodes)); - sv_numareanodes = 0; - SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); -} - - -/* -=============== -SV_UnlinkEdict - -=============== -*/ -void SV_UnlinkEdict (edict_t *ent) -{ - if (!ent->area.prev) - return; // not linked in anywhere - RemoveLink (&ent->area); - ent->area.prev = ent->area.next = NULL; -} - - -/* -==================== -SV_TouchLinks -==================== -*/ -void SV_TouchLinks ( edict_t *ent, areanode_t *node ) -{ - link_t *l, *next; - edict_t *touch; - int old_self, old_other; - -// touch linked edicts - for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) - { - next = l->next; - touch = EDICT_FROM_AREA(l); - if (touch == ent) - continue; - if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) - continue; - if (ent->v.absmin[0] > touch->v.absmax[0] - || ent->v.absmin[1] > touch->v.absmax[1] - || ent->v.absmin[2] > touch->v.absmax[2] - || ent->v.absmax[0] < touch->v.absmin[0] - || ent->v.absmax[1] < touch->v.absmin[1] - || ent->v.absmax[2] < touch->v.absmin[2] ) - continue; - old_self = pr_global_struct->self; - old_other = pr_global_struct->other; - - pr_global_struct->self = EDICT_TO_PROG(touch); - pr_global_struct->other = EDICT_TO_PROG(ent); - pr_global_struct->time = sv.time; - PR_ExecuteProgram (touch->v.touch); - - pr_global_struct->self = old_self; - pr_global_struct->other = old_other; - } - -// recurse down both sides - if (node->axis == -1) - return; - - if ( ent->v.absmax[node->axis] > node->dist ) - SV_TouchLinks ( ent, node->children[0] ); - if ( ent->v.absmin[node->axis] < node->dist ) - SV_TouchLinks ( ent, node->children[1] ); -} - - -/* -=============== -SV_FindTouchedLeafs - -=============== -*/ -void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) -{ - mplane_t *splitplane; - mleaf_t *leaf; - int sides; - int leafnum; - - if (node->contents == CONTENTS_SOLID) - return; - -// add an efrag if the node is a leaf - - if ( node->contents < 0) - { - if (ent->num_leafs == MAX_ENT_LEAFS) - return; - - leaf = (mleaf_t *)node; - leafnum = leaf - sv.worldmodel->leafs - 1; - - ent->leafnums[ent->num_leafs] = leafnum; - ent->num_leafs++; - return; - } - -// NODE_MIXED - - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane); - -// recurse down the contacted sides - if (sides & 1) - SV_FindTouchedLeafs (ent, node->children[0]); - - if (sides & 2) - SV_FindTouchedLeafs (ent, node->children[1]); -} - -/* -=============== -SV_LinkEdict - -=============== -*/ -void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) -{ - areanode_t *node; - - if (ent->area.prev) - SV_UnlinkEdict (ent); // unlink from old position - - if (ent == sv.edicts) - return; // don't add the world - - if (ent->free) - return; - -// set the abs box - -#ifdef QUAKE2 - if (ent->v.solid == SOLID_BSP && - (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) - { // expand for rotation - float max, v; - int i; - - max = 0; - for (i=0 ; i<3 ; i++) - { - v =fabs( ent->v.mins[i]); - if (v > max) - max = v; - v =fabs( ent->v.maxs[i]); - if (v > max) - max = v; - } - for (i=0 ; i<3 ; i++) - { - ent->v.absmin[i] = ent->v.origin[i] - max; - ent->v.absmax[i] = ent->v.origin[i] + max; - } - } - else -#endif - { - VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); - VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax); - } - -// -// to make items easier to pick up and allow them to be grabbed off -// of shelves, the abs sizes are expanded -// - if ((int)ent->v.flags & FL_ITEM) - { - ent->v.absmin[0] -= 15; - ent->v.absmin[1] -= 15; - ent->v.absmax[0] += 15; - ent->v.absmax[1] += 15; - } - else - { // because movement is clipped an epsilon away from an actual edge, - // we must fully check even when bounding boxes don't quite touch - ent->v.absmin[0] -= 1; - ent->v.absmin[1] -= 1; - ent->v.absmin[2] -= 1; - ent->v.absmax[0] += 1; - ent->v.absmax[1] += 1; - ent->v.absmax[2] += 1; - } - -// link to PVS leafs - ent->num_leafs = 0; - if (ent->v.modelindex) - SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); - - if (ent->v.solid == SOLID_NOT) - return; - -// find the first node that the ent's box crosses - node = sv_areanodes; - while (1) - { - if (node->axis == -1) - break; - if (ent->v.absmin[node->axis] > node->dist) - node = node->children[0]; - else if (ent->v.absmax[node->axis] < node->dist) - node = node->children[1]; - else - break; // crosses the node - } - -// link it in - - if (ent->v.solid == SOLID_TRIGGER) - InsertLinkBefore (&ent->area, &node->trigger_edicts); - else - InsertLinkBefore (&ent->area, &node->solid_edicts); - -// if touch_triggers, touch all entities at this node and decend for more - if (touch_triggers) - SV_TouchLinks ( ent, sv_areanodes ); -} - - - -/* -=============================================================================== - -POINT TESTING IN HULLS - -=============================================================================== -*/ - -#if !id386 - -/* -================== -SV_HullPointContents - -================== -*/ -int SV_HullPointContents (hull_t *hull, int num, vec3_t p) -{ - float d; - dclipnode_t *node; - mplane_t *plane; - - while (num >= 0) - { - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("SV_HullPointContents: bad node number"); - - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; - - if (plane->type < 3) - d = p[plane->type] - plane->dist; - else - d = DotProduct (plane->normal, p) - plane->dist; - if (d < 0) - num = node->children[1]; - else - num = node->children[0]; - } - - return num; -} - -#endif // !id386 - - -/* -================== -SV_PointContents - -================== -*/ -int SV_PointContents (vec3_t p) -{ - int cont; - - cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); - if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN) - cont = CONTENTS_WATER; - return cont; -} - -int SV_TruePointContents (vec3_t p) -{ - return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); -} - -//=========================================================================== - -/* -============ -SV_TestEntityPosition - -This could be a lot more efficient... -============ -*/ -edict_t *SV_TestEntityPosition (edict_t *ent) -{ - trace_t trace; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent); - - if (trace.startsolid) - return sv.edicts; - - return NULL; -} - - -/* -=============================================================================== - -LINE TESTING IN HULLS - -=============================================================================== -*/ - -// 1/32 epsilon to keep floating point happy -#define DIST_EPSILON (0.03125) - -/* -================== -SV_RecursiveHullCheck - -================== -*/ -qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) -{ - dclipnode_t *node; - mplane_t *plane; - float t1, t2; - float frac; - int i; - vec3_t mid; - int side; - float midf; - -// check for empty - if (num < 0) - { - if (num != CONTENTS_SOLID) - { - trace->allsolid = false; - if (num == CONTENTS_EMPTY) - trace->inopen = true; - else - trace->inwater = true; - } - else - trace->startsolid = true; - return true; // empty - } - - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("SV_RecursiveHullCheck: bad node number"); - -// -// find the point distances -// - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; - - if (plane->type < 3) - { - t1 = p1[plane->type] - plane->dist; - t2 = p2[plane->type] - plane->dist; - } - else - { - t1 = DotProduct (plane->normal, p1) - plane->dist; - t2 = DotProduct (plane->normal, p2) - plane->dist; - } - -#if 1 - if (t1 >= 0 && t2 >= 0) - return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - if (t1 < 0 && t2 < 0) - return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); -#else - if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) - return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) - return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); -#endif - -// put the crosspoint DIST_EPSILON pixels on the near side - if (t1 < 0) - frac = (t1 + DIST_EPSILON)/(t1-t2); - else - frac = (t1 - DIST_EPSILON)/(t1-t2); - if (frac < 0) - frac = 0; - if (frac > 1) - frac = 1; - - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); - - side = (t1 < 0); - -// move up to the node - if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) - return false; - -#ifdef PARANOID - if (SV_HullPointContents (sv_hullmodel, mid, node->children[side]) - == CONTENTS_SOLID) - { - Con_Printf ("mid PointInHullSolid\n"); - return false; - } -#endif - - if (SV_HullPointContents (hull, node->children[side^1], mid) - != CONTENTS_SOLID) -// go past the node - return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); - - if (trace->allsolid) - return false; // never got out of the solid area - -//================== -// the other side of the node is solid, this is the impact point -//================== - if (!side) - { - VectorCopy (plane->normal, trace->plane.normal); - trace->plane.dist = plane->dist; - } - else - { - VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); - trace->plane.dist = -plane->dist; - } - - while (SV_HullPointContents (hull, hull->firstclipnode, mid) - == CONTENTS_SOLID) - { // shouldn't really happen, but does occasionally - frac -= 0.1; - if (frac < 0) - { - trace->fraction = midf; - VectorCopy (mid, trace->endpos); - Con_DPrintf ("backup past 0\n"); - return false; - } - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); - } - - trace->fraction = midf; - VectorCopy (mid, trace->endpos); - - return false; -} - - -/* -================== -SV_ClipMoveToEntity - -Handles selection or creation of a clipping hull, and offseting (and -eventually rotation) of the end points -================== -*/ -trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) -{ - trace_t trace; - vec3_t offset; - vec3_t start_l, end_l; - hull_t *hull; - -// fill in a default trace - memset (&trace, 0, sizeof(trace_t)); - trace.fraction = 1; - trace.allsolid = true; - VectorCopy (end, trace.endpos); - -// get the clipping hull - hull = SV_HullForEntity (ent, mins, maxs, offset); - - VectorSubtract (start, offset, start_l); - VectorSubtract (end, offset, end_l); - -#ifdef QUAKE2 - // rotate start and end into the models frame of reference - if (ent->v.solid == SOLID_BSP && - (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) - { - vec3_t a; - vec3_t forward, right, up; - vec3_t temp; - - AngleVectors (ent->v.angles, forward, right, up); - - VectorCopy (start_l, temp); - start_l[0] = DotProduct (temp, forward); - start_l[1] = -DotProduct (temp, right); - start_l[2] = DotProduct (temp, up); - - VectorCopy (end_l, temp); - end_l[0] = DotProduct (temp, forward); - end_l[1] = -DotProduct (temp, right); - end_l[2] = DotProduct (temp, up); - } -#endif - -// trace a line through the apropriate clipping hull - SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); - -#ifdef QUAKE2 - // rotate endpos back to world frame of reference - if (ent->v.solid == SOLID_BSP && - (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) - { - vec3_t a; - vec3_t forward, right, up; - vec3_t temp; - - if (trace.fraction != 1) - { - VectorSubtract (vec3_origin, ent->v.angles, a); - AngleVectors (a, forward, right, up); - - VectorCopy (trace.endpos, temp); - trace.endpos[0] = DotProduct (temp, forward); - trace.endpos[1] = -DotProduct (temp, right); - trace.endpos[2] = DotProduct (temp, up); - - VectorCopy (trace.plane.normal, temp); - trace.plane.normal[0] = DotProduct (temp, forward); - trace.plane.normal[1] = -DotProduct (temp, right); - trace.plane.normal[2] = DotProduct (temp, up); - } - } -#endif - -// fix trace up by the offset - if (trace.fraction != 1) - VectorAdd (trace.endpos, offset, trace.endpos); - -// did we clip the move? - if (trace.fraction < 1 || trace.startsolid ) - trace.ent = ent; - - return trace; -} - -//=========================================================================== - -/* -==================== -SV_ClipToLinks - -Mins and maxs enclose the entire area swept by the move -==================== -*/ -void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) -{ - link_t *l, *next; - edict_t *touch; - trace_t trace; - -// touch linked edicts - for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) - { - next = l->next; - touch = EDICT_FROM_AREA(l); - if (touch->v.solid == SOLID_NOT) - continue; - if (touch == clip->passedict) - continue; - if (touch->v.solid == SOLID_TRIGGER) - Sys_Error ("Trigger in clipping list"); - - if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP) - continue; - - if (clip->boxmins[0] > touch->v.absmax[0] - || clip->boxmins[1] > touch->v.absmax[1] - || clip->boxmins[2] > touch->v.absmax[2] - || clip->boxmaxs[0] < touch->v.absmin[0] - || clip->boxmaxs[1] < touch->v.absmin[1] - || clip->boxmaxs[2] < touch->v.absmin[2] ) - continue; - - if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) - continue; // points never interact - - // might intersect, so do an exact clip - if (clip->trace.allsolid) - return; - if (clip->passedict) - { - if (PROG_TO_EDICT(touch->v.owner) == clip->passedict) - continue; // don't clip against own missiles - if (PROG_TO_EDICT(clip->passedict->v.owner) == touch) - continue; // don't clip against owner - } - - if ((int)touch->v.flags & FL_MONSTER) - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end); - else - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end); - if (trace.allsolid || trace.startsolid || - trace.fraction < clip->trace.fraction) - { - trace.ent = touch; - if (clip->trace.startsolid) - { - clip->trace = trace; - clip->trace.startsolid = true; - } - else - clip->trace = trace; - } - else if (trace.startsolid) - clip->trace.startsolid = true; - } - -// recurse down both sides - if (node->axis == -1) - return; - - if ( clip->boxmaxs[node->axis] > node->dist ) - SV_ClipToLinks ( node->children[0], clip ); - if ( clip->boxmins[node->axis] < node->dist ) - SV_ClipToLinks ( node->children[1], clip ); -} - - -/* -================== -SV_MoveBounds -================== -*/ -void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) -{ -#if 0 -// debug to test against everything -boxmins[0] = boxmins[1] = boxmins[2] = -9999; -boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999; -#else - int i; - - for (i=0 ; i<3 ; i++) - { - if (end[i] > start[i]) - { - boxmins[i] = start[i] + mins[i] - 1; - boxmaxs[i] = end[i] + maxs[i] + 1; - } - else - { - boxmins[i] = end[i] + mins[i] - 1; - boxmaxs[i] = start[i] + maxs[i] + 1; - } - } -#endif -} - -/* -================== -SV_Move -================== -*/ -trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict) -{ - moveclip_t clip; - int i; - - memset ( &clip, 0, sizeof ( moveclip_t ) ); - -// clip to world - clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end ); - - clip.start = start; - clip.end = end; - clip.mins = mins; - clip.maxs = maxs; - clip.type = type; - clip.passedict = passedict; - - if (type == MOVE_MISSILE) - { - for (i=0 ; i<3 ; i++) - { - clip.mins2[i] = -15; - clip.maxs2[i] = 15; - } - } - else - { - VectorCopy (mins, clip.mins2); - VectorCopy (maxs, clip.maxs2); - } - -// create the bounding box of the entire move - SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); - -// clip to entities - SV_ClipToLinks ( sv_areanodes, &clip ); - - return clip.trace; -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// world.c -- world query functions + +#include "quakedef.h" + +/* + +entities never clip against themselves, or their owner + +line of sight checks trace->crosscontent, but bullets don't + +*/ + + +typedef struct +{ + vec3_t boxmins, boxmaxs;// enclose the test object along entire move + float *mins, *maxs; // size of the moving object + vec3_t mins2, maxs2; // size when clipping against mosnters + float *start, *end; + trace_t trace; + int type; + edict_t *passedict; +} moveclip_t; + + +int SV_HullPointContents (hull_t *hull, int num, vec3_t p); + +/* +=============================================================================== + +HULL BOXES + +=============================================================================== +*/ + + +static hull_t box_hull; +static dclipnode_t box_clipnodes[6]; +static mplane_t box_planes[6]; + +/* +=================== +SV_InitBoxHull + +Set up the planes and clipnodes so that the six floats of a bounding box +can just be stored out and get a proper hull_t structure. +=================== +*/ +void SV_InitBoxHull (void) +{ + int i; + int side; + + box_hull.clipnodes = box_clipnodes; + box_hull.planes = box_planes; + box_hull.firstclipnode = 0; + box_hull.lastclipnode = 5; + + for (i=0 ; i<6 ; i++) + { + box_clipnodes[i].planenum = i; + + side = i&1; + + box_clipnodes[i].children[side] = CONTENTS_EMPTY; + if (i != 5) + box_clipnodes[i].children[side^1] = i + 1; + else + box_clipnodes[i].children[side^1] = CONTENTS_SOLID; + + box_planes[i].type = i>>1; + box_planes[i].normal[i>>1] = 1; + } + +} + + +/* +=================== +SV_HullForBox + +To keep everything totally uniform, bounding boxes are turned into small +BSP trees instead of being compared directly. +=================== +*/ +hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs) +{ + box_planes[0].dist = maxs[0]; + box_planes[1].dist = mins[0]; + box_planes[2].dist = maxs[1]; + box_planes[3].dist = mins[1]; + box_planes[4].dist = maxs[2]; + box_planes[5].dist = mins[2]; + + return &box_hull; +} + + + +/* +================ +SV_HullForEntity + +Returns a hull that can be used for testing or clipping an object of mins/maxs +size. +Offset is filled in to contain the adjustment that must be added to the +testing object's origin to get a point to use with the returned hull. +================ +*/ +hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) +{ + model_t *model; + vec3_t size; + vec3_t hullmins, hullmaxs; + hull_t *hull; + +// decide which clipping hull to use, based on the size + if (ent->v.solid == SOLID_BSP) + { // explicit hulls in the BSP model + if (ent->v.movetype != MOVETYPE_PUSH) + Sys_Error ("SOLID_BSP without MOVETYPE_PUSH"); + + model = sv.models[ (int)ent->v.modelindex ]; + + if (!model || model->type != mod_brush) + Sys_Error ("MOVETYPE_PUSH with a non bsp model"); + + VectorSubtract (maxs, mins, size); + if (size[0] < 3) + hull = &model->hulls[0]; + else if (size[0] <= 32) + hull = &model->hulls[1]; + else + hull = &model->hulls[2]; + +// calculate an offset value to center the origin + VectorSubtract (hull->clip_mins, mins, offset); + VectorAdd (offset, ent->v.origin, offset); + } + else + { // create a temp hull from bounding box sizes + + VectorSubtract (ent->v.mins, maxs, hullmins); + VectorSubtract (ent->v.maxs, mins, hullmaxs); + hull = SV_HullForBox (hullmins, hullmaxs); + + VectorCopy (ent->v.origin, offset); + } + + + return hull; +} + +/* +=============================================================================== + +ENTITY AREA CHECKING + +=============================================================================== +*/ + +typedef struct areanode_s +{ + int axis; // -1 = leaf node + float dist; + struct areanode_s *children[2]; + link_t trigger_edicts; + link_t solid_edicts; +} areanode_t; + +#define AREA_DEPTH 4 +#define AREA_NODES 32 + +static areanode_t sv_areanodes[AREA_NODES]; +static int sv_numareanodes; + +/* +=============== +SV_CreateAreaNode + +=============== +*/ +areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) +{ + areanode_t *anode; + vec3_t size; + vec3_t mins1, maxs1, mins2, maxs2; + + anode = &sv_areanodes[sv_numareanodes]; + sv_numareanodes++; + + ClearLink (&anode->trigger_edicts); + ClearLink (&anode->solid_edicts); + + if (depth == AREA_DEPTH) + { + anode->axis = -1; + anode->children[0] = anode->children[1] = NULL; + return anode; + } + + VectorSubtract (maxs, mins, size); + if (size[0] > size[1]) + anode->axis = 0; + else + anode->axis = 1; + + anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); + VectorCopy (mins, mins1); + VectorCopy (mins, mins2); + VectorCopy (maxs, maxs1); + VectorCopy (maxs, maxs2); + + maxs1[anode->axis] = mins2[anode->axis] = anode->dist; + + anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2); + anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1); + + return anode; +} + +/* +=============== +SV_ClearWorld + +=============== +*/ +void SV_ClearWorld (void) +{ + SV_InitBoxHull (); + + memset (sv_areanodes, 0, sizeof(sv_areanodes)); + sv_numareanodes = 0; + SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); +} + + +/* +=============== +SV_UnlinkEdict + +=============== +*/ +void SV_UnlinkEdict (edict_t *ent) +{ + if (!ent->area.prev) + return; // not linked in anywhere + RemoveLink (&ent->area); + ent->area.prev = ent->area.next = NULL; +} + + +/* +==================== +SV_TouchLinks +==================== +*/ +void SV_TouchLinks ( edict_t *ent, areanode_t *node ) +{ + link_t *l, *next; + edict_t *touch; + int old_self, old_other; + +// touch linked edicts + for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) + { + next = l->next; + touch = EDICT_FROM_AREA(l); + if (touch == ent) + continue; + if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) + continue; + if (ent->v.absmin[0] > touch->v.absmax[0] + || ent->v.absmin[1] > touch->v.absmax[1] + || ent->v.absmin[2] > touch->v.absmax[2] + || ent->v.absmax[0] < touch->v.absmin[0] + || ent->v.absmax[1] < touch->v.absmin[1] + || ent->v.absmax[2] < touch->v.absmin[2] ) + continue; + old_self = pr_global_struct->self; + old_other = pr_global_struct->other; + + pr_global_struct->self = EDICT_TO_PROG(touch); + pr_global_struct->other = EDICT_TO_PROG(ent); + pr_global_struct->time = sv.time; + PR_ExecuteProgram (touch->v.touch); + + pr_global_struct->self = old_self; + pr_global_struct->other = old_other; + } + +// recurse down both sides + if (node->axis == -1) + return; + + if ( ent->v.absmax[node->axis] > node->dist ) + SV_TouchLinks ( ent, node->children[0] ); + if ( ent->v.absmin[node->axis] < node->dist ) + SV_TouchLinks ( ent, node->children[1] ); +} + + +/* +=============== +SV_FindTouchedLeafs + +=============== +*/ +void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) +{ + mplane_t *splitplane; + mleaf_t *leaf; + int sides; + int leafnum; + + if (node->contents == CONTENTS_SOLID) + return; + +// add an efrag if the node is a leaf + + if ( node->contents < 0) + { + if (ent->num_leafs == MAX_ENT_LEAFS) + return; + + leaf = (mleaf_t *)node; + leafnum = leaf - sv.worldmodel->leafs - 1; + + ent->leafnums[ent->num_leafs] = leafnum; + ent->num_leafs++; + return; + } + +// NODE_MIXED + + splitplane = node->plane; + sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane); + +// recurse down the contacted sides + if (sides & 1) + SV_FindTouchedLeafs (ent, node->children[0]); + + if (sides & 2) + SV_FindTouchedLeafs (ent, node->children[1]); +} + +/* +=============== +SV_LinkEdict + +=============== +*/ +void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) +{ + areanode_t *node; + + if (ent->area.prev) + SV_UnlinkEdict (ent); // unlink from old position + + if (ent == sv.edicts) + return; // don't add the world + + if (ent->free) + return; + +// set the abs box + +#ifdef QUAKE2 + if (ent->v.solid == SOLID_BSP && + (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) + { // expand for rotation + float max, v; + int i; + + max = 0; + for (i=0 ; i<3 ; i++) + { + v =fabs( ent->v.mins[i]); + if (v > max) + max = v; + v =fabs( ent->v.maxs[i]); + if (v > max) + max = v; + } + for (i=0 ; i<3 ; i++) + { + ent->v.absmin[i] = ent->v.origin[i] - max; + ent->v.absmax[i] = ent->v.origin[i] + max; + } + } + else +#endif + { + VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); + VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax); + } + +// +// to make items easier to pick up and allow them to be grabbed off +// of shelves, the abs sizes are expanded +// + if ((int)ent->v.flags & FL_ITEM) + { + ent->v.absmin[0] -= 15; + ent->v.absmin[1] -= 15; + ent->v.absmax[0] += 15; + ent->v.absmax[1] += 15; + } + else + { // because movement is clipped an epsilon away from an actual edge, + // we must fully check even when bounding boxes don't quite touch + ent->v.absmin[0] -= 1; + ent->v.absmin[1] -= 1; + ent->v.absmin[2] -= 1; + ent->v.absmax[0] += 1; + ent->v.absmax[1] += 1; + ent->v.absmax[2] += 1; + } + +// link to PVS leafs + ent->num_leafs = 0; + if (ent->v.modelindex) + SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); + + if (ent->v.solid == SOLID_NOT) + return; + +// find the first node that the ent's box crosses + node = sv_areanodes; + while (1) + { + if (node->axis == -1) + break; + if (ent->v.absmin[node->axis] > node->dist) + node = node->children[0]; + else if (ent->v.absmax[node->axis] < node->dist) + node = node->children[1]; + else + break; // crosses the node + } + +// link it in + + if (ent->v.solid == SOLID_TRIGGER) + InsertLinkBefore (&ent->area, &node->trigger_edicts); + else + InsertLinkBefore (&ent->area, &node->solid_edicts); + +// if touch_triggers, touch all entities at this node and decend for more + if (touch_triggers) + SV_TouchLinks ( ent, sv_areanodes ); +} + + + +/* +=============================================================================== + +POINT TESTING IN HULLS + +=============================================================================== +*/ + +#if !id386 + +/* +================== +SV_HullPointContents + +================== +*/ +int SV_HullPointContents (hull_t *hull, int num, vec3_t p) +{ + float d; + dclipnode_t *node; + mplane_t *plane; + + while (num >= 0) + { + if (num < hull->firstclipnode || num > hull->lastclipnode) + Sys_Error ("SV_HullPointContents: bad node number"); + + node = hull->clipnodes + num; + plane = hull->planes + node->planenum; + + if (plane->type < 3) + d = p[plane->type] - plane->dist; + else + d = DotProduct (plane->normal, p) - plane->dist; + if (d < 0) + num = node->children[1]; + else + num = node->children[0]; + } + + return num; +} + +#endif // !id386 + + +/* +================== +SV_PointContents + +================== +*/ +int SV_PointContents (vec3_t p) +{ + int cont; + + cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN) + cont = CONTENTS_WATER; + return cont; +} + +int SV_TruePointContents (vec3_t p) +{ + return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); +} + +//=========================================================================== + +/* +============ +SV_TestEntityPosition + +This could be a lot more efficient... +============ +*/ +edict_t *SV_TestEntityPosition (edict_t *ent) +{ + trace_t trace; + + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent); + + if (trace.startsolid) + return sv.edicts; + + return NULL; +} + + +/* +=============================================================================== + +LINE TESTING IN HULLS + +=============================================================================== +*/ + +// 1/32 epsilon to keep floating point happy +#define DIST_EPSILON (0.03125) + +/* +================== +SV_RecursiveHullCheck + +================== +*/ +qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) +{ + dclipnode_t *node; + mplane_t *plane; + float t1, t2; + float frac; + int i; + vec3_t mid; + int side; + float midf; + +// check for empty + if (num < 0) + { + if (num != CONTENTS_SOLID) + { + trace->allsolid = false; + if (num == CONTENTS_EMPTY) + trace->inopen = true; + else + trace->inwater = true; + } + else + trace->startsolid = true; + return true; // empty + } + + if (num < hull->firstclipnode || num > hull->lastclipnode) + Sys_Error ("SV_RecursiveHullCheck: bad node number"); + +// +// find the point distances +// + node = hull->clipnodes + num; + plane = hull->planes + node->planenum; + + if (plane->type < 3) + { + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; + } + else + { + t1 = DotProduct (plane->normal, p1) - plane->dist; + t2 = DotProduct (plane->normal, p2) - plane->dist; + } + +#if 1 + if (t1 >= 0 && t2 >= 0) + return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); + if (t1 < 0 && t2 < 0) + return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); +#else + if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) + return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); + if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) + return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); +#endif + +// put the crosspoint DIST_EPSILON pixels on the near side + if (t1 < 0) + frac = (t1 + DIST_EPSILON)/(t1-t2); + else + frac = (t1 - DIST_EPSILON)/(t1-t2); + if (frac < 0) + frac = 0; + if (frac > 1) + frac = 1; + + midf = p1f + (p2f - p1f)*frac; + for (i=0 ; i<3 ; i++) + mid[i] = p1[i] + frac*(p2[i] - p1[i]); + + side = (t1 < 0); + +// move up to the node + if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) + return false; + +#ifdef PARANOID + if (SV_HullPointContents (sv_hullmodel, mid, node->children[side]) + == CONTENTS_SOLID) + { + Con_Printf ("mid PointInHullSolid\n"); + return false; + } +#endif + + if (SV_HullPointContents (hull, node->children[side^1], mid) + != CONTENTS_SOLID) +// go past the node + return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); + + if (trace->allsolid) + return false; // never got out of the solid area + +//================== +// the other side of the node is solid, this is the impact point +//================== + if (!side) + { + VectorCopy (plane->normal, trace->plane.normal); + trace->plane.dist = plane->dist; + } + else + { + VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); + trace->plane.dist = -plane->dist; + } + + while (SV_HullPointContents (hull, hull->firstclipnode, mid) + == CONTENTS_SOLID) + { // shouldn't really happen, but does occasionally + frac -= 0.1; + if (frac < 0) + { + trace->fraction = midf; + VectorCopy (mid, trace->endpos); + Con_DPrintf ("backup past 0\n"); + return false; + } + midf = p1f + (p2f - p1f)*frac; + for (i=0 ; i<3 ; i++) + mid[i] = p1[i] + frac*(p2[i] - p1[i]); + } + + trace->fraction = midf; + VectorCopy (mid, trace->endpos); + + return false; +} + + +/* +================== +SV_ClipMoveToEntity + +Handles selection or creation of a clipping hull, and offseting (and +eventually rotation) of the end points +================== +*/ +trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) +{ + trace_t trace; + vec3_t offset; + vec3_t start_l, end_l; + hull_t *hull; + +// fill in a default trace + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + trace.allsolid = true; + VectorCopy (end, trace.endpos); + +// get the clipping hull + hull = SV_HullForEntity (ent, mins, maxs, offset); + + VectorSubtract (start, offset, start_l); + VectorSubtract (end, offset, end_l); + +#ifdef QUAKE2 + // rotate start and end into the models frame of reference + if (ent->v.solid == SOLID_BSP && + (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) + { + vec3_t a; + vec3_t forward, right, up; + vec3_t temp; + + AngleVectors (ent->v.angles, forward, right, up); + + VectorCopy (start_l, temp); + start_l[0] = DotProduct (temp, forward); + start_l[1] = -DotProduct (temp, right); + start_l[2] = DotProduct (temp, up); + + VectorCopy (end_l, temp); + end_l[0] = DotProduct (temp, forward); + end_l[1] = -DotProduct (temp, right); + end_l[2] = DotProduct (temp, up); + } +#endif + +// trace a line through the apropriate clipping hull + SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); + +#ifdef QUAKE2 + // rotate endpos back to world frame of reference + if (ent->v.solid == SOLID_BSP && + (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) + { + vec3_t a; + vec3_t forward, right, up; + vec3_t temp; + + if (trace.fraction != 1) + { + VectorSubtract (vec3_origin, ent->v.angles, a); + AngleVectors (a, forward, right, up); + + VectorCopy (trace.endpos, temp); + trace.endpos[0] = DotProduct (temp, forward); + trace.endpos[1] = -DotProduct (temp, right); + trace.endpos[2] = DotProduct (temp, up); + + VectorCopy (trace.plane.normal, temp); + trace.plane.normal[0] = DotProduct (temp, forward); + trace.plane.normal[1] = -DotProduct (temp, right); + trace.plane.normal[2] = DotProduct (temp, up); + } + } +#endif + +// fix trace up by the offset + if (trace.fraction != 1) + VectorAdd (trace.endpos, offset, trace.endpos); + +// did we clip the move? + if (trace.fraction < 1 || trace.startsolid ) + trace.ent = ent; + + return trace; +} + +//=========================================================================== + +/* +==================== +SV_ClipToLinks + +Mins and maxs enclose the entire area swept by the move +==================== +*/ +void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) +{ + link_t *l, *next; + edict_t *touch; + trace_t trace; + +// touch linked edicts + for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) + { + next = l->next; + touch = EDICT_FROM_AREA(l); + if (touch->v.solid == SOLID_NOT) + continue; + if (touch == clip->passedict) + continue; + if (touch->v.solid == SOLID_TRIGGER) + Sys_Error ("Trigger in clipping list"); + + if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP) + continue; + + if (clip->boxmins[0] > touch->v.absmax[0] + || clip->boxmins[1] > touch->v.absmax[1] + || clip->boxmins[2] > touch->v.absmax[2] + || clip->boxmaxs[0] < touch->v.absmin[0] + || clip->boxmaxs[1] < touch->v.absmin[1] + || clip->boxmaxs[2] < touch->v.absmin[2] ) + continue; + + if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) + continue; // points never interact + + // might intersect, so do an exact clip + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (PROG_TO_EDICT(touch->v.owner) == clip->passedict) + continue; // don't clip against own missiles + if (PROG_TO_EDICT(clip->passedict->v.owner) == touch) + continue; // don't clip against owner + } + + if ((int)touch->v.flags & FL_MONSTER) + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end); + else + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end); + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + if (clip->trace.startsolid) + { + clip->trace = trace; + clip->trace.startsolid = true; + } + else + clip->trace = trace; + } + else if (trace.startsolid) + clip->trace.startsolid = true; + } + +// recurse down both sides + if (node->axis == -1) + return; + + if ( clip->boxmaxs[node->axis] > node->dist ) + SV_ClipToLinks ( node->children[0], clip ); + if ( clip->boxmins[node->axis] < node->dist ) + SV_ClipToLinks ( node->children[1], clip ); +} + + +/* +================== +SV_MoveBounds +================== +*/ +void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) +{ +#if 0 +// debug to test against everything +boxmins[0] = boxmins[1] = boxmins[2] = -9999; +boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999; +#else + int i; + + for (i=0 ; i<3 ; i++) + { + if (end[i] > start[i]) + { + boxmins[i] = start[i] + mins[i] - 1; + boxmaxs[i] = end[i] + maxs[i] + 1; + } + else + { + boxmins[i] = end[i] + mins[i] - 1; + boxmaxs[i] = start[i] + maxs[i] + 1; + } + } +#endif +} + +/* +================== +SV_Move +================== +*/ +trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict) +{ + moveclip_t clip; + int i; + + memset ( &clip, 0, sizeof ( moveclip_t ) ); + +// clip to world + clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end ); + + clip.start = start; + clip.end = end; + clip.mins = mins; + clip.maxs = maxs; + clip.type = type; + clip.passedict = passedict; + + if (type == MOVE_MISSILE) + { + for (i=0 ; i<3 ; i++) + { + clip.mins2[i] = -15; + clip.maxs2[i] = 15; + } + } + else + { + VectorCopy (mins, clip.mins2); + VectorCopy (maxs, clip.maxs2); + } + +// create the bounding box of the entire move + SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); + +// clip to entities + SV_ClipToLinks ( sv_areanodes, &clip ); + + return clip.trace; +} + diff --git a/WinQuake/world.h b/WinQuake/world.h index cddb94f..4d8c39a 100644 --- a/WinQuake/world.h +++ b/WinQuake/world.h @@ -1,78 +1,78 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// world.h - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -typedef struct -{ - qboolean allsolid; // if true, plane is not valid - qboolean startsolid; // if true, the initial point was in a solid area - qboolean inopen, inwater; - float fraction; // time completed, 1.0 = didn't hit anything - vec3_t endpos; // final position - plane_t plane; // surface normal at impact - edict_t *ent; // entity the surface is on -} trace_t; - - -#define MOVE_NORMAL 0 -#define MOVE_NOMONSTERS 1 -#define MOVE_MISSILE 2 - - -void SV_ClearWorld (void); -// called after the world model has been loaded, before linking any entities - -void SV_UnlinkEdict (edict_t *ent); -// call before removing an entity, and before trying to move one, -// so it doesn't clip against itself -// flags ent->v.modified - -void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); -// Needs to be called any time an entity changes origin, mins, maxs, or solid -// flags ent->v.modified -// sets ent->v.absmin and ent->v.absmax -// if touchtriggers, calls prog functions for the intersected triggers - -int SV_PointContents (vec3_t p); -int SV_TruePointContents (vec3_t p); -// returns the CONTENTS_* value from the world at the given point. -// does not check any entities at all -// the non-true version remaps the water current contents to content_water - -edict_t *SV_TestEntityPosition (edict_t *ent); - -trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); -// mins and maxs are reletive - -// if the entire move stays in a solid volume, trace.allsolid will be set - -// if the starting point is in a solid, it will be allowed to move out -// to an open area - -// nomonsters is used for line of sight or edge testing, where mosnters -// shouldn't be considered solid objects - -// passedict is explicitly excluded from clipping checks (normally NULL) +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// world.h + +typedef struct +{ + vec3_t normal; + float dist; +} plane_t; + +typedef struct +{ + qboolean allsolid; // if true, plane is not valid + qboolean startsolid; // if true, the initial point was in a solid area + qboolean inopen, inwater; + float fraction; // time completed, 1.0 = didn't hit anything + vec3_t endpos; // final position + plane_t plane; // surface normal at impact + edict_t *ent; // entity the surface is on +} trace_t; + + +#define MOVE_NORMAL 0 +#define MOVE_NOMONSTERS 1 +#define MOVE_MISSILE 2 + + +void SV_ClearWorld (void); +// called after the world model has been loaded, before linking any entities + +void SV_UnlinkEdict (edict_t *ent); +// call before removing an entity, and before trying to move one, +// so it doesn't clip against itself +// flags ent->v.modified + +void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); +// Needs to be called any time an entity changes origin, mins, maxs, or solid +// flags ent->v.modified +// sets ent->v.absmin and ent->v.absmax +// if touchtriggers, calls prog functions for the intersected triggers + +int SV_PointContents (vec3_t p); +int SV_TruePointContents (vec3_t p); +// returns the CONTENTS_* value from the world at the given point. +// does not check any entities at all +// the non-true version remaps the water current contents to content_water + +edict_t *SV_TestEntityPosition (edict_t *ent); + +trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); +// mins and maxs are reletive + +// if the entire move stays in a solid volume, trace.allsolid will be set + +// if the starting point is in a solid, it will be allowed to move out +// to an open area + +// nomonsters is used for line of sight or edge testing, where mosnters +// shouldn't be considered solid objects + +// passedict is explicitly excluded from clipping checks (normally NULL) diff --git a/WinQuake/worlda.s b/WinQuake/worlda.s index 630902a..9c59ed8 100644 --- a/WinQuake/worlda.s +++ b/WinQuake/worlda.s @@ -1,22 +1,22 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ // // worlda.s // x86 assembly-language server testing stuff diff --git a/WinQuake/wq.bat b/WinQuake/wq.bat index 90881fe..5734fb5 100644 --- a/WinQuake/wq.bat +++ b/WinQuake/wq.bat @@ -1,42 +1,42 @@ -@echo off -if x%1==xfast goto fast -if x%1==xsafe goto safe -if x%1==xverysafe goto verysafe -if x%1==xfastvid goto fastvid -if x%1==xfastsnd goto fastsnd -if x%1==xmax goto max - -echo ------------------------------------------------------------------- -echo Options for running WinQuake: -echo wq max: all features on, but doesn't work on all systems -echo wq fast: maximum speed, but doesn't work on all systems -echo wq fastvid: maximum video speed, but safer, probably slower sound -echo wq fastsnd: maximum sound speed, but safer, probably slower video -echo wq safe: very likely to run, but may be slower -echo wq verysafe: almost sure to run, but probably slower, and no sound -echo ------------------------------------------------------------------- -goto done - -:max -winquake -dinput %2 %3 %4 %5 %6 %7 %8 %9 -goto done - -:fast -winquake %2 %3 %4 %5 %6 %7 %8 %9 -goto done - -:fastvid -winquake -wavonly %2 %3 %4 %5 %6 %7 %8 %9 -goto done - -:fastsnd -winquake -nodirectdraw -nowindirect %2 %3 %4 %5 %6 %7 %8 %9 -goto done - -:safe -winquake -nodirectdraw -nowindirect -wavonly %2 %3 %4 %5 %6 %7 %8 %9 -goto done - -:verysafe -winquake -dibonly -nosound -nojoy %2 %3 %4 %5 %6 %7 %8 %9 -:done +@echo off +if x%1==xfast goto fast +if x%1==xsafe goto safe +if x%1==xverysafe goto verysafe +if x%1==xfastvid goto fastvid +if x%1==xfastsnd goto fastsnd +if x%1==xmax goto max + +echo ------------------------------------------------------------------- +echo Options for running WinQuake: +echo wq max: all features on, but doesn't work on all systems +echo wq fast: maximum speed, but doesn't work on all systems +echo wq fastvid: maximum video speed, but safer, probably slower sound +echo wq fastsnd: maximum sound speed, but safer, probably slower video +echo wq safe: very likely to run, but may be slower +echo wq verysafe: almost sure to run, but probably slower, and no sound +echo ------------------------------------------------------------------- +goto done + +:max +winquake -dinput %2 %3 %4 %5 %6 %7 %8 %9 +goto done + +:fast +winquake %2 %3 %4 %5 %6 %7 %8 %9 +goto done + +:fastvid +winquake -wavonly %2 %3 %4 %5 %6 %7 %8 %9 +goto done + +:fastsnd +winquake -nodirectdraw -nowindirect %2 %3 %4 %5 %6 %7 %8 %9 +goto done + +:safe +winquake -nodirectdraw -nowindirect -wavonly %2 %3 %4 %5 %6 %7 %8 %9 +goto done + +:verysafe +winquake -dibonly -nosound -nojoy %2 %3 %4 %5 %6 %7 %8 %9 +:done diff --git a/WinQuake/wqreadme.txt b/WinQuake/wqreadme.txt index 9ba2f1b..faee316 100644 --- a/WinQuake/wqreadme.txt +++ b/WinQuake/wqreadme.txt @@ -1,1119 +1,1119 @@ --------------------------- -| wqreadme.txt | -| WinQuake documentation | -| 3/21/97 | --------------------------- - -WinQuake (WQ) is a native Win32 version of Quake, and will run on -either Win95 or Windows NT 4.0 or later. It is designed to take -advantage of whatever enhanced video, sound, and input capabilities -(such as DirectX or VESA VBE video modes) are present, but has -fallback functionality so it can run on any Win95 or NT 4.0 or later -system, even if neither DirectX nor VESA VBE is available. You may -experience problems running WQ on some systems, because driver and -operating-system support for game functionality are not yet mature -under Win32, and many bugs and incompatibilities remain in those -components. If you encounter what seems to be a bug, first please -check through the list of known problems, below. If your problem -doesn't appear on the list, please fill out and submit the WQ bug -report at http://www.idsoftware.com/contact/. - -The material accompanying Quake is the reference for all -non-Windows-related matters concerning WinQuake; in terms of gameplay, -WQ is the same as Quake. This file contains Windows-related -information only. - -The rest of this document is organized as follows: - -Installing and running WinQuake -Common problems and workarounds -A bit about how WQ video works -Video command-line switches -A bit about how WQ sound works -Sound command-line switches -Notes on networking -Notes on the mouse -Log of changes to documentation -Special thanks - - ------------------------------------ -| Installing and running WinQuake | ------------------------------------ - -In order to run WinQuake, you must first have Quake installed. -Assuming Quake is installed in the standard directory, c:\quake, -unzip the WinQuake zip file into c:\quake. The following files -from the zip file must be present in order for WQ to run: - -winquake.exe -pmpro16.dll -pmpro32.dll -wdir16.dll -wdir32.dll -wdirnop.com -wdirnop.pif - -Then you can run WinQuake by making c:\quake the current directory, -typing "winquake" and pressing the Enter key. Alternatively, you can -use wq.bat to run WinQuake. The wq batch file requires one parameter -describing how to configure WQ for performance; just type "wq" to get -a list of the six options. The first of the six options is - -wq fast - -This is the same as typing "winquake"; this runs WinQuake in an -aggressive configuration that is likely to yield the best performance -if it runs successfully on your system, but which has a risk of -causing WinQuake or even your system to crash if there are bugs or -incompatibilities in your video or sound drivers. Alternatively, you -can use - -wq safe - -to run WinQuake in a conservative configuration, likely to run -on almost all machines with no problems, but possibly with slower -graphics, fewer high-resolution modes, and delayed sound. Or you -can run - -wq verysafe - -to run WinQuake in a very conservative configuration that is pretty -much guaranteed to run, but will probably have slow performance, and -will have no sound. Two other options are - -wq fastvid - -which has maximum video performance, but greater sound latency (delay -until the sound is heard), and - -wq fastsnd - -which uses more conservative video modes, but low-latency sound. - -(One odd note is that DirectSound has much lower-latency sound than -wave sound, but is currently quite a bit slower overall. Thus you -may find that "wq fastvid" is actually faster, by as much as 5-10%, -than "wq fast"; however, it may not feel faster, because the sound -will lag.) - -Finally, you can use - -wq max - -which is the same as wq fast, but turns on DirectInput, which -provides more responsive mouse control, but does not work properly -on all systems. - -Note that DirectX is not required for WQ to run, but WQ will -automatically take advantage of DirectSound and DirectDraw if they -are present. If DirectSound is not present, there will generally be -considerable sound latency (sound will become audible several hundred -milliseconds after the event that caused it). Note also that there -are currently no true DirectSound drivers for Windows NT, so WQ will -always run using wave output on NT, and will consequently have lagged -sound. See below for information about obtaining DirectX if you do -not have it. - -Note that VESA VBE modes aren't required for WQ to run, but WQ will -automatically make VESA modes available if they're present. Your BIOS -may already have VESA VBE 2.0 support built in, but most BIOSes -don't. Worse, some BIOSes do have VESA VBE 2.0 built-in, but have -buggy implementations, which may prevent you from being able to run -the faster configurations of WQ. An easy way to get reliable VESA 2.0 -support is by obtaining SciTech Display Doctor; see below for -further information. WQ can also use VBE/AF 1.0 and greater modes; -again, SciTech Display Doctor is the commonest way to get VBE/AF -support. - -Note that winquake -dedicated completely replaces the old winded -dedicated Win32 server, which is now obsolete. - -WinQuake normally uses half the physical memory in your system for its -heap, but not less than 8.5 Mb and not more than 16 Mb. You can -override this with "-heapsize n", where n is the amount of memory to -allocate for the heap, in Kb. - -To use the joystick, you must bring down the console by pressing the -tilde ('~') key, and type "joystick 1"; you can disable the -joystick with "joystick 0" at any time. The joystick setting -remains in effect for subsequent WinQuake sessions until changed, so -you only need to do joystick 1 once to enable the joystick. If the -joystick somehow causes problems that keep you from being able to run -WinQuake at all, you can start WinQuake -nojoy to complete disable the -joystick for that session. - - ------------------------------------ -| Common problems and workarounds | ------------------------------------ - -WQ crashes or won't run ------------------------ - -If WQ refuses to run or crashes on your system, try running -it using "wq safe" or "wq verysafe". Or you can use command-line -switches: - -winquake -nodirectdraw -nowindirect -wavonly - -This will almost certainly solve your problem; however, it may result -in lagged sound (a long delay from action to hearing the sound), may -result in fewer or slower high-res video modes, and the mouse may be -somewhat less responsive. If this does work, you can try removing -each of the command-line switches until you identify the one that -fixes the problem, thereby sacrificing as little functionality as -possible. - -If the above command line does not fix your problems, try: - -winquake -dibonly -nosound - -which forces WQ into silent operation with bare-bones video support -and no use of DirectInput for mouse input (the normal Windows mouse -APIs are used instead). Again, if this works, try removing switches -until you identify the needed one. - -Both of the above command lines are quick fixes. Often, the problem -is caused by outdated or buggy DirectX drivers or code, and can -frequently be completely fixed simply by installing the latest -Microsoft-supplied version of DirectX, which you may be able to find -on http://www.microsoft.com/mediadev/download/directx.exe, although -the availability and location of the DirectX file changes -periodically; note that at last check, this is a 3.4 Mb file. (Be -aware, though, that sometimes Microsoft's DirectX drivers don't -support features that the manufacturers' drivers do support, such as -display refresh rate control.) - -One known problem of this sort involves the current SB16 drivers from -Creative Labs, which cause WQ to crash on some machines. The -DirectSound drivers from Microsoft, available via the above-mentioned -URL, fix this problem. - -It can also sometimes help to get the latest Windows drivers for your -video adapter or sound card (although as the SB16 example indicates, -this is not always a good idea), and for video boards that have flash -BIOSes, it can sometimes help to get the latest BIOS upgrade. - - -How do I select fullscreen or windowed WQ operation? ----------------------------------------------------- -Check out WQ's new, spiffy Video menu, accessible from the Options -menu. There are now two types of modes listed, windowed and -fullscreen. You can make any of these modes the current and/or -default mode, just as in DOS Quake. If you make a windowed mode the -default, WQ will still briefly start up in fullscreen mode, then -switch to windowed; if this is a problem, use the -startwindowed -command-line switch. More complete video control is available -through the console, as described in the "A bit about how WQ video -works" section, below. - - -Gee, I wish I could use a mouse to play WQ with in a window ------------------------------------------------------------ -You can! While in a windowed mode, go to the Options menu. At the -bottom, you'll find a new selection that lets you choose to have the -mouse active when you're in a window. Of course, if you do this, -you'll have to use the keyboard (Alt-Tab, the Windows key, Ctrl-Esc, -Alt-Esc, or Shift-Alt-Tab) to switch away from WQ. - - -Serial/modem menu is missing ----------------------------- -WQ currently does not support direct connect serial or modem play. - - -DOS Quake reports unknown variables on startup after running WQ ---------------------------------------------------------------- -WQ uses some console variables that do not exist in DOS Quake, and -some of these are automatically archived in config.cfg when you exit -WQ. If you then start DOS Quake, DOS Quake will complain that it -doesn't recognize those variables. You will also lose the settings -of these variables when you return to WQ. Apart from losing the -settings, this is harmless; ignore it. - - -Problems running WQ on NT 3.51 ------------------------------- -NT 3.51 isn't supported by WQ. - - -WQ crashes while switching modes or Alt-Tabbing ------------------------------------------------ -So far, all cases of this seem to be tied to Creative Lab's SB16 sound -drivers, and have been fixed by getting the latest DirectX drivers, as -described above. Alternatively, you should be able to fix this either -by not switching modes or Alt-Tabbing, or by running -wavonly to -disable DirectSound support. - - -WQ sometimes runs pretty slowly fullscreen ------------------------------------------- -There are several possible reasons for this, starting with "You have a -slow computer." Assuming that's not the case, if you don't have -either DirectDraw or SciTech Display Doctor installed (see the "A bit -about how WQ video works" section), it would probably be a good thing -to install one or the other, because slow operation can be a result -of slow copying or stretching of pixels to the screen by a Windows -driver, something that's eliminated by both DirectDraw and Display -Doctor. You can also sometimes get a faster 320x200 mode on Win95 by -doing vid_describemodes, then using vid_mode to select a non-VGA -320x200 mode, as described in the "A bit about how WQ video works" -section. - -You can also try using a primary sound buffer on Win95 (this doesn't -work on NT) by using the -primarysound command-line switch; this can -improve performance by several percent, but does not work on all -systems, and can result in odd sound effects on some systems when -minimizing WQ or switching the focus away from it. If you use this -switch, please don't report sound bugs; it's in there purely for you -to use if it helps you, and we know it has problems on many systems. -Finally, you can use -wavonly to select wave sound; this will increase -your sound latency (sounds will be heard later than they should), but -allows WQ to run 5-10% faster on some systems. That's about all you -can do to speed up fullscreen WQ on Win95, other than shrinking the -active area of the screen with the screen size control in the Options -menu. - -NT 4.0 comes with DirectX installed, but doesn't have any resolutions -lower than 640x480. In order to support a lower-resolution 320x240 -mode, WQ has NT double each pixel in both directions to get enough -pixels for 640x480. The extra stretching costs some performance, the -result being that NT can seem sluggish on all but high-end Pentiums -and Pentium Pros. (In fact, depending on the quality of your driver's -stretching code, it can sometimes be faster to run WQ at 640x480 than -320x240-stretched on NT.) One thing that can help on NT is switching -to 640x480, then using the Options menu to shrink the active area of -the screen. - -A common cause of slowness running in a window is having the desktop -run in 16- or 32-bpp mode. WQ is an 8-bpp application, and it slows -things down if pixels have to be translated from 8-bpp to 16- or -32-bpp. (Note that this is generally a problem only when running in a -window; fullscreen apps rarely suffer from this.) - - -Sound is sluggish on NT ------------------------ -NT doesn't have any real DirectSound drivers yet, so there's no way to -do quick-response sound on NT. When DirectSound drivers for NT -appear, WQ's sound should automatically be snappier. - - -Sound breaks up or gets choppy, especially in menus ---------------------------------------------------- -This is generally a sign that WQ's frame rate is too low on your -system. Try reducing resolution or shrinking the active area of the -screen. In some circumstances, it may help to set the console -variable _snd_mixahead to a larger value. - - -The color black doesn't change with palette flashes sometimes -------------------------------------------------------------- -Normally, DirectDraw lets WQ change all 256 colors, so when a palette -flash happens, we can change all the colors, including black. -However, on NT DirectDraw currently doesn't allow changing black; -likewise, on both NT and Win95, black can't be changed in a window, -either a normal window or fullscreen. Consequently, in some modes and -in a window, some parts of the WQ screen (such as the sigils on the -status bar and the spray where a shotgun blast hits) stay black when -the palette flashes. There is no workaround. - - -Problems can result if Office shortcut bar is running ------------------------------------------------------ -Various odd behaviors, especially with sound, have been reported if -the Office shortcut bar is running while WQ is running. If you -experience odd problems, you might try shutting down the Office -shortcut bar and see if that fixes anything. - - -Other apps fail to play sound while WinQuake is running -------------------------------------------------------- -The sound hardware is currently not a fully shareable resource on -Win32. Consequently, while WQ is running, it always has the sound -hardware allocated to itself, to make sure that sound is never lost to -another app. This means that normally (when WQ is using DirectSound), -apps that use wave sound (most non-game apps) will not be able to play -sound while WQ is running, even if WQ is minimized or not the active -app, although other DirectSound apps will be able to play sound when -WQ is not the active app. If WQ is using wave sound rather than -DirectSound (either because -wavonly is used on the command line, or -because there is no DirectSound driver, as is always the case on NT), -then no other app will be able to play any sound while WQ is running, -period. - - -WQ doesn't have quite the right colors when it’s not the active app -------------------------------------------------------------------- -We're working on fixing this. But WQ puts everything back again as -soon as it is reactivated, and anyway, when it’s not active, you can’t -actually do anything in WQ, so it doesn’t really matter anyway, right? - - -Desktop is weird colors when WQ runs windowed ---------------------------------------------- -WQ needs all 256 colors to look right and run fast, which causes it to -have to change some of the 20 colors used to draw the desktop. - - -Sometimes Permedia boards crash unless -nowindirect is used ------------------------------------------------------------ -It looks like this is probably a Permedia driver bug, so it might help -if you get the most recent drivers. - - -Right-click on WQ button in task bar to close doesn’t work as expected ----------------------------------------------------------------------- -In some modes, right-clicking on the WQ task bar button doesn't work -the way you'd expect. We're trying to fix this, but if it's a -problem, don't right-click. - - -Screen saver never kicks in when running WQ fullscreen ------------------------------------------------------- -It does work windowed, but when WinQuake is fullscreen, it completely -owns the screen and doesn't share it with anyone, even the -screensaver. If you use Alt-Tab to minimize WQ, the screensaver will -then be enabled, so Alt-Tab away from WQ if you're leaving your -computer alone for a while and want the screensaver to be able to kick -in. - - -WQ doesn’t work in a window in 16-color mode --------------------------------------------- -That’s 16 *colors*, not 16-bpp. If you’re still running a 16-color -desktop, run WQ fullscreen. - - -Can't minimize window while mouse active ----------------------------------------- -When running in a window with the mouse active as a WQ input device, -there is no easy way to minimize the window, because the system menu -can't be brought up from the keyboard (because some of you use Alt -and Spacebar for playing the game), and the mouse can't be used to -manipulate the window because it's controlling WQ. To minimize, you -can disable the mouse for WQ and use it to minimize the window. Or -on Win95 you can Alt-Tab away from WQ, then use the mouse to -minimize (this doesn't work on NT, where clicking on the window -controls just reactivates WQ). Or you can bind a key to the -vid_minimize command, as in - -bind m "vid_minimize" - -and press that key to minimize the window. - - -Window controls don't work on NT when mouse enabled ---------------------------------------------------- -When running in a window on NT with the mouse enabled (so you can use -the mouse to play WQ), if you Alt-Tab away from WQ, then use the mouse -to click on the WQ system menu control, or the minimize, maximize, or -close controls, the controls are ignored and WQ just reactivates. - - -Mouse sometimes vanishes in system menu on Win95 ------------------------------------------------- -On Win95, if WQ is running in a window with the mouse enabled (so you -can use the mouse to play WQ), if you Alt-Tab away, then click on the -system menu, the menu comes up, but the mouse vanishes. However, you -can still use the keyboard to select system menu items, or to exit -the system menu. - - -WQ behaves oddly if Scandisk starts defragmenting -------------------------------------------------- -If WQ is running fullscreen on Win95 when Scandisk starts an automatic -defragging, WQ is forced to minimize, and when it is brought back up, -may either be in a strange mode where it runs one frame for each -keystroke (in which case Alt-Tab generally fixes things), or may hang -the system. We don't know what the problem is right now, but you may -want to make sure you don't leave WQ sitting there fullscreen -overnight if you have automatic defragging. - - -Hang reported with zero sound volume ------------------------------------- -When sound is turned all the way down via the WQ menus, hangs have -been reported. - - -Joystick worked fine with earlier versions of WinQuake but not now ------------------------------------------------------------------- -The joystick was enabled by default in earlier versions of -WinQuake, but quite a few people reported serious problems that -forced them to disable the joystick--even some people who didn't -have a joystick attached. Since most people don't have joysticks, -we've decided to disable the joystick by default, and let people -who do want to use it set joystick 1 in the console (WinQuake -remembers this setting, so this only needs to be done once). - - -WQ runs very slowly when it has the focus under NT --------------------------------------------------- -In one case, WQ ran very slowly when it had the focus, but fast when -it didn't (obviously this is only visible in windowed modes). The -problem turned out to be that NT had a Sidewinder 3D Pro joystick -driver installed; when the driver was removed, things were fine. -If you see a similar problem, check whether WQ is detecting that -your system has a joystick when you don't think it should; if so, -try doing "joystick 0", or -nojoy on the command line, and see if -that fixes it. If so, there's something flaky in your system -joystick setup. - - -Joystick doesn't seem calibrated properly ------------------------------------------ -WQ relies on the information about your joystick stored in the -system registry. If the joystick seems miscalibrated, run the -joystick applet and recalibrate and see if that fixes things. - - -Playdemo fails across multiple levels -------------------------------------- -If "record" is used to record a client-side demo, bad things will -happen on playback via playdemo if a level change is recorded. -(Timedemo works fine.) This is unfortunate, but WinQuake -internals make this not fixable without a good chance of -breaking something more important, so it'll have to stay this way. - - -Alt-Tab fullscreen only works sometimes ---------------------------------------- -I know it seems that way, but actually the trick is that on Win95 -it only works if you let go of Tab before you let go of Alt. -This is due to a Windows quirk involving what key sequences are -passed along, so you'll have to work around it by remembering to -let go of Tab first. - - -MS-DOS windows get scrunched on Alt-Tab ---------------------------------------- -This is a quirk of Windows; when you run WinQuake in a low-res -mode, sometimes when you exit WinQuake or Alt-Tab back to the -desktop, any open MS-DOS windows will be scrunched down to the -size of the low-res mode. There is no known workaround. - - -Dprint in progs doesn't work ----------------------------- -Dprint means "developer print," so it only works if the developer -console variable is set to 1. It was a bug in earlier versions that -it worked even when developer was set to 0. - - -Some DirectDraw modes flicker badly and look wrong --------------------------------------------------- -Page flipping doesn't work properly in some modes on some -systems, particularly when using some DirectDraw modes. You -can work around this by setting the console variable -vid_nopageflip to 1, then setting the desired mode (note -that the vid_nopageflip setting does not take effect until -the next mode set after the setting is changed). Bear in -mind, though, that the vid_nopageflip setting is remembered -until it is explicitly changed again, meaning that once you -change it, it thereafter applies to all modes, even if you -exit and restart WinQuake. - - -The Windows key doesn't do anything fullscreen on Win95 -------------------------------------------------------- -True. This is a minor bug we haven't figured out how to fix yet. -You'll have to use Ctrl-Esc, Alt-Tab, or Alt-Esc to switch away. - - -My default mode is windowed, but WQ goes fullscreen first ---------------------------------------------------------- -For internal reasons, WQ has to pick a single mode to always -initialize when it starts up, before it sets whatever default you've -selected. We've chosen fullscreen mode, because that's the way most -people will play. If this is a problem for you, however, you can -run WQ with the -startwindowed command-line parameter. - - -Some high-resolution video modes flicker or fail to initialize --------------------------------------------------------------- -We think these problems are all fixed, but if not, they have to -do with triple-buffering in some modes on some DirectDraw drivers. -If you encounter this problem, either don't use the problem modes -or try using the -notriplebuf command-line parameter to turn off -triple buffering. Note, though, that turning off triple-buffering -can reduce performance in some modes, so do this only if needed. - - -Right-click doesn't work right on minimized WinQuake ----------------------------------------------------- -If you right-click on minimized WinQuake on the task bar, the -Close selection in the right-click menu doesn't work; you have -to restore WQ before you can exit it. Also, the cursor vanishes -over the right-click menu, although it still works. - - -The screen briefly blanks when you exit WQ ------------------------------------------- -We're trying to fix this, but it's not harmful, just a mite ugly. - - -QBENCH doesn't work with WinQuake ---------------------------------- -We've had a report that QBENCH doesn't work with WinQuake, but -haven't had a chance to look into it yet. - - -MWAVE sound loses focus ------------------------ -We've had a report that on a ThinkPad with MWAVE sound, WQ loses -sound focus (and thus sound) every few seconds. - - -Desktop doesn't reset to proper resolution on WQ exit ------------------------------------------------------ -We've had a report that on exiting WQ, the desktop didn't reset -to the proper dimensions. This may be a bug with the Matrox -drivers, but we're not sure. If it's a problem and newer -drivers don't fix it, you can run -dibonly, which solves the -problem but can cost some performance. - - -Palette goes bad periodically on #9 Imagine card ------------------------------------------------- -There's only one report of this, so maybe it's a flaky board, -or maybe it's a driver bug. Newer drivers might help. - - -System with Packard Bell sound card III crashes on CapsLock ------------------------------------------------------------ -This appears to be the result of buggy DirectSound drivers; --wavonly makes the problem go away. - - -Dvorak keyboard mapping ignored -------------------------------- -WQ is hardwired for QWERTY. - - -Cursor messed up after running WQ ---------------------------------- -This is a Windows driver bug; the driver isn't restoring the -cursor properly on return from fullscreen WQ to the desktop. -Try newer drivers. - - -Dedicated server runs very slowly while typing at console ---------------------------------------------------------- -When you type at a dedicated server's console, the game runs -very slowly for everyone who's connected. - - -Ctrl-Alt-Del on NT sometimes doesn't allow return to WQ -------------------------------------------------------- -This happens on some machines while running WQ fullscreen. -If you experience this problem, the only workaround is not -to press Ctrl-Alt-Del while fullscreen; Alt-Tab away first. - - -Many fast Alt-Tabs on Win95 sometimes disable WQ input ------------------------------------------------------- -If you Alt-Tab fast lots of times on Win95 with WQ running -fullscreen, sometimes you end up in fullscreen WQ, with the -game not accepting any keyboard input (so there's no way to -exit). The only workaround is to not do lots of fast -Alt-Tabs (why you'd want to, I'm not sure). - - - ----------------------------------- -| A bit about how WQ video works | ----------------------------------- - -WQ has the built-in ability to draw into windows (both normal, framed -desktop windows and fullscreen, borderless windows). It also has -built- in support for VGA 320x200 graphics, and supports DirectDraw, -VESA VBE 2.0 and VESA VBE/AF (Accelerator Functions) graphics modes, -if those are available. - -WQ does not require DirectDraw, but in order for DirectDraw modes to -be available, you must have DirectDraw installed; some systems come -with it preinstalled, but if it's not on your system, you can download -it from http://www.microsoft.com/mediadev/download/directx.exe (the -exact URL may vary), and install it. - -WQ does not require VESA VBE, but in order for VESA VBE modes to be -available, your graphics card must be VESA VBE 2.0 or VBE/AF -compliant; a VESA driver can either be built into the BIOS of your -graphics card, or loadable via software. If you don't have a VESA VBE -driver, Scitech Display Doctor, available from Scitech Software, will -update most graphics cards to VESA VBE 2.0 and VBE/AF. - - -SciTech Display Doctor ----------------------- -If you are having problems with your video drivers, or if you would -like to take a shot at improving your video performance in WQ, you may -want to try out SciTech Display Doctor (SDD). SDD works on just about -any graphics card and it can do several things that can make WQ run -better on your system: - -1. It will update your graphics card to be compatible with VESA VBE -2.0 and VESA VBE/AF (Accelerator Functions). These modes will usually -give you the best performance in WQ (which is often but not always -faster than your current performance). - -2. It creates low-resolution modes on your graphics card. -Low-resolution video modes (such as 320x240, 400x300 and 512x384) -allow you to adjust the level of detail in WQ so you can get the best -balance between performance and image quality. - -The latest version of SciTech Display Doctor can be obtained from the -following locations: - -www: http://www.scitechsoft.com -ftp: ftp.scitechsoft.com -CIS: GO SCITECH -AOL: Keyword SciTech - -SciTech can be contacted at: - -email: info@scitechsoft.com - -SciTech Software, Inc. -505 Wall Street -Chico, CA 95926-1989 -916-894-8400 -916-894-9069 FAX - - -Video modes supported in Win95 ------------------------------- -What all this means is that on Win95, WQ will always be able to run in -the following modes: - -1) in a window -2) fullscreen 320x200 VGA mode 0x13 -3) fullscreen high-resolution of some sort - -Category #3 can be any of several configurations. On Win95, if either -DirectDraw or VESA VBE modes are available, then all the DirectDraw -and VESA modes will be presented as high-res choices. (320x200 will -always default to VGA mode 0x13.) In the case that a given resolution -is supported by both DirectDraw and VESA, the VESA mode will be used. -(However, the command-line switch -nowindirect can turn off VESA modes -entirely.) If neither DirectDraw nor VESA modes are available, then -high-resolution modes will be provided by using fullscreen, borderless -windows in whatever resolutions the Windows driver supports, usually -starting at 640x480 and going up. - - -Video Modes Supported in Windows NT ------------------------------------ -NT is similar but not identical, because neither VESA VBE modes nor -VGA mode 0x13 are available. On NT, WQ will always be able to run in -the following modes: - -1) in a window -2) fullscreen high-resolution of some sort - -On NT, category #2 can be one of two configurations. If DirectDraw -modes are available, then those will be the high-res choices; -otherwise, fullscreen, borderless windows will be used in whatever -resolutions the driver supports, usually starting at 640x480 and going -up. Because there is normally no low-resolution mode such as 320x200 -or 320x240 on NT, a pseudo low-res mode is created by rendering at -320x240, then stretching the image by doubling it in each direction -while copying it to a 640x480 screen. However, stretching performance -depends on the driver, and can be slow, so sometimes 640x480 is -actually faster than 320x240 on NT. - -The bottom line here is that you can generally just use the Video menu -and pick one of the modes and be happy. In some cases, though, you -may need to use command-line switches (described next) to get the -types of modes you want. One useful tip is to go into the console and -do vid_describemodes, which lists all the modes WQ makes available on -your machine given the command-line switches you've used. Each mode -is followed by the name of the internal WQ driver that supports it, so -you can tell which modes are DirectDraw, VESA, and so on, as follows: - -WINDOWED: WQ runs in a normal window -FULLSCREEN DIB: fullscreen borderless window -FULLSCREEN VGA8.DRV: VGA 320x200 mode -FULLSCREEN DDRAW8.DRV: DirectDraw mode -FULLSCREEN LINEAR8.DRV: VESA VBE 2.0+ mode -FULLSCREEN ACCEL8.DRV: VESA VBE/AF (Accelerator Functions) mode - (note that WQ does not take advantage of - VBE/AF acceleration; so far as WQ is - concerned VBE/AF is the same as normal VBE) - -You can use vid_mode from the console to set any of these modes. So, -for example, if you see that there are two 320x200 modes (such as one -VGA mode 0x13, normally mode 3, and one VESA mode, normally mode 4), -you can choose the VESA mode, which will often be faster, with -vid_mode 4. (You can make it the default by setting -_vid_default_mode_win to the mode number.) - -There's more to the windowed modes than you might think. 320x240 is -just what you’d expect, but 640x480 is actually rendered at 320x240 -and stretched up to 640x480, because most machines can’t handle the -performance demands of real 640x480 rendering. Likewise, 800x600 is a -stretched 400x300. Actually, though, vid_mode 2 (the 800x600 mode) is -a user-configurable mode. By setting the following console variables, -you can change the characteristics of vid_mode 2: - -vid_config_x: width of mode 2 window - -vid_config_y: height of mode 2 window - -vid_stretch_by_2: whether to render at half-resolution in each -direction and stretch up to the specified size in mode 2, or render at -full resolution. - -After setting these variables in the console, do a vid_forcemode 2, -and you’ll have the window you specified. Note that after making -these changes, the new resolution will show up as the third windowed -mode in the Video menu. - -If you don't have WQ mouse play enabled in windowed mode, you can also -go from windowed to fullscreen mode simply by clicking on the maximize -button. The mode switched to is controlled by the vid_fullscreen_mode -console variable, and defaults to mode 3. - -Other video console commands include: - -vid_fullscreen: switch to the mode specified by the -vid_fullscreen_mode console variable. - -vid_windowed: switch to the mode specified by the vid_windowed_mode -console variable. - -Vid_fullscreen and vid_windowed can be bound to keys, so it's possible -to flip between windowed and fullscreen with a single key press. - -Also, vid_minimize minimizes the WinQuake window if and only if -WinQuake is running in a windowed mode. You can bind a key to -the commands "vid_windowed; wait; vid_minimize" to minimize WQ -regardless of whether you're running in windowed or fullscreen mode. - -You can turn off page flipping by setting the console variable -vid_nopageflip to 1, then setting a new mode. (Note that the -vid_nopageflip setting does not take effect until the next mode set.) -Some systems run faster with page flipping turned off; also, page -flipping does not work properly on some adapters, and vid_nopageflip -is a workaround for this. Note that vid_nopageflip is a persistent -variable; it retains its setting until it is explicitly changed again, -even across multiple WinQuake sessions. - -The vid_forcemode console command sets the specified mode, even if -it's the same as the current mode (normally the mode set only happens -if the new mode differs from the current mode). This is generally -useful only if you've modified the characteristics of video mode 2 -(the configurable window) while you're in mode 2, and want to force -the new characteristics to take effect. - -Whenever you switch to running WinQuake in a window, the window is -placed at the same location it was in the last time WinQuake ran -in a window. You can reset the window position to the upper left -by using the -resetwinpos command-line switch. The window position -is stored in the vid_window_x and vid_window_y console variables. - - - -------------------------------- -| Video command-line switches | -------------------------------- - -The full list of video-related command-line switches is: - --dibonly: WQ will use only windows (both normal, framed windows on the -desktop and fullscreen, borderless windows), not any direct hardware -access modes such as DirectDraw or VESA modes, or even VGA 320x200 -mode. This is the closest thing to a guaranteed-to-run fullscreen -mode WQ has. - --nowindirect: WQ will not try to use VESA VBE 2.0 modes, or VBE/AF -1.0 or later modes. Note that if there are both DirectDraw and VESA -modes for a given resolution, WQ will normally use the VESA mode; --nowindirect allows DirectDraw modes to be the preferred choice for -all resolutions except 320x200. This can be useful if WQ is crashing -because of a buggy VESA driver. - --nodirectdraw: WQ will not try to use DirectDraw modes. This can be -useful if WQ is crashing because of a buggy DirectDraw driver. - --novbeaf: WQ will not try to use VBE/AF 1.0 or later modes. - --startwindowed: WQ will come up in a windowed mode, without going -fullscreen even during initialization. - --noforcevga: normally, WQ uses VGA mode 0x13 for the default 320x200 -mode, even if a DirectDraw or VESA 320x200 mode exists. However, -DirectDraw and VESA modes can be considerably faster than mode 0x13, -because they can set up a linear framebuffer with higher memory -bandwidth. If you specify -noforcevga, the default 320x200 mode in -the menu will be a DirectDraw or VESA mode if one exists. This has no -effect on modes selected via the console variable vid_mode, and if -320x200 is already your video mode, -noforcevga doesn't do anything -until you use the menu to select another mode, then select 320x200 -again. (So if your default mode is 320x200 and you then specify --noforcevga, switch away to some other mode and then back to 320x200 -to get the potentially faster 320x200 mode.) The downside to this -switch is that DirectDraw and VESA modes can cause problems in some -systems, due to driver bugs or hardware incompatibilities; if you -experience problems with this switch, don't use it. - --noautostretch: don't stretch windowed modes selected with --startwindowed to double resolution. - --nofulldib: don't use fullscreen, borderless windows, even if there -are no DirectDraw or VESA modes available. - --allow360: allow listing of 360-wide modes in the video mode menu. -These are normally filtered out to make sure the menu doesn't get too -full, which could cause high-res modes not to be displayed. - --notriplebuf: prevent triple-buffered page flipping (rather than double- -buffered). This may result in slower performance, but is a workaround -if you encounter problems with flicker or initialization failure, which -could possibly happen in some modes with some DirectDraw drivers. - - - ----------------------------------- -| A bit about how WQ sound works | ----------------------------------- - -WQ can use either DirectSound or Windows wave output to generate -sound. If DirectSound is available, it is used; if not, if wave sound -is available it is used; and if neither is available, there is no -sound. DirectSound results in the best sound quality, and also the -lowest-latency sound; use it if you can, because you will be happier -with the results. (Note, though, that no NT sound drivers yet support -DirectSound.) Wave sound will often have high latency, lagging the -events that generate sound by hundreds of milliseconds on some -machines. - -You can tell what kind of sound WQ uses on your system by looking at -the startup portion of the console; you will see either "DirectSound -initialized" or "Wave sound initialized" (neither message is printed -if there's no sound). Any sound failure messages will also be printed -in the startup portion of the console. - -Note that WQ generates sound only when it is the active app, the one -with the input focus. - - - -------------------------------- -| Sound command-line switches | -------------------------------- - -The full list of sound-related command-line switches is: - --wavonly: don’t use DirectSound, but use wave sound if available. -Note that wave sound is generally faster than DirectSound, but has -considerably greater latency. This switch is redundant on NT, because -all sound output on current NT drivers is wave sound. - --nosound: don’t output any sound. - --primarysound: use DirectSound primary buffer output. This is -generally faster than normal secondary buffer output, but does not -work in some systems, and produces odd sound glitches on minimization -and focus switching in other systems. Use it at your own risk, and -please do not report sound bugs if you're using this switch. - --snoforceformat: WQ will not try to force the sound hardware to 11 -KHz, 16 bits per sample. This may be useful if DirectSound is failing -for no apparent reason, but generally WQ will produce better sound and -better performance if this switch is not used. - - - ------------------------ -| Notes on networking | ------------------------ - -The winsock TCP/IP driver will not cause a dial-up internet connection -to automatically start up when Quake is started. If you start Quake -with it inactive, the connection will be activated when you either try -to connect to a server or search for local servers. - -The local IP address will not always be known at startup. If it is -currently unknown the menu will display "INADDR_ANY". This will be -replaced with the real address when it is known. The IP address will -become known when you try to connect to a server, you search for local -servers, or you start a server. - -For multi-homed machines (machines with more than one network adapter -and IP adress), you can force WinQuake to bind to a specific IP -address. There is a command line option "-ip" that takes an IP -address as its parameter. - - - ----------------------- -| Notes on the mouse | ----------------------- - -If DirectInput is installed and functioning, WinQuake can use it for -mouse input, but does not do so automatically because DirectInput does -not work properly on all systems. DirectInput can be enabled via the -command-line switch -dinput. If DirectInput is not available or is -not enabled, WinQuake uses the normal Windows mouse APIs instead. -DirectInput provides slightly smoother motion; also, it tends to be -more responsive to fast spinning motions, and we recommend that you use -it if it works properly on your system. You can determine if WQ uses -DirectInput on your system when you use -dinput by checking for -"DirectInput initialized" in the startup console text. If not, you -might try installing DirectX 3 (note, though, that as I write this -there is no released DirectInput support for Windows NT, only Win95). - - - ------------------------------------ -| Log of changes to documentation | ------------------------------------ - -*** WinQuake 0.994 *** - -Fixed bug where in some cases involving IPX, whenever a new person -entered the game, a current player got dumped. - -Added DirectInput mouse support, and the -dinput command-line to -enable it. - -Added -notriplebuf to disable triple buffering to work around -possible problems with some modes on some DirectDraw drivers. - -Added remembering last window position, and restoring that, rather -than centering the window, whenever WinQuake runs in a window. -Can be reset with the -resetwinpos command-line switch. - -Added the vid_minimize command, which minimizes WinQuake if and only -if the current mode is windowed. - -Made it so WinQuake no longer gets suspended when Alt-Tab is used to -switch away from a fullscreen session. The means you can Alt-Tab -away from fullscreen WinQuake without losing a connection to a -Quake server. - -Added vid_nopageflip console variable to turn off page flipping, and -documented page flipping problems this can be used to work around. - -Documented that Del-Ctrl-Alt (in that order) causes WinQuake to -fault on Win95. - -Fixed the winsock TCP/IP driver so it will not cause a dial-up -internet connection to automatically start up when Quake is started. -If you start Quake with the internet connection already active, there -will be no difference. If you start Quake with it inactive, the -connection will be activated when you either try to connect to a -server or search for local servers. - -The local IP address will not always be known at startup now. If it -is currently unknown the menu will display "INADDR_ANY". This -will be replaced with the real address when it is known. The IP -address will become known when: you try to connect to a server, -you search for local servers, or you start a server. - -For multi-homed machines (machines with more than one network -adapter and IP adress), you can now force WinQuake to bind to a -specific IP adress. There is a new command line option "-ip" that -takes an IP address as its parameter. - -Added vid_fullscreen_mode and ability to select that mode by -clicking on the maximize button. Added two commands: -vid_fullscreen to switch to vid_fullscreen_mode, and -vid_windowed to switch to vid_windowed mode. - -Changed joystick default to disabled; now it only works if the -joystick cvar is set to 1; however, this setting now remains in -effect permanently. Added joystick documentation below. - -Documented dprint only works if developer set to 1. - -Documented scrunching of MS-DOS windows on Alt-Tab. - -Documented that NT versions earlier to 4.0 are not supported. - -Added DirectInput support for devices such as First Person -Gaming's Assassin controller. All buttons should now -be configurable in WinQuake. - -Fixed bug where when low-res fullscreen DIB modes selected from -the menu sometimes ran very slowly or produced garbled displays. - -Fixed bug where 1.06 and earlier save files couldn't be loaded -by WinQuake. - -Removed "Net play pauses every few seconds" bug; it was determined -not to be a bug, just an artifact of network play. - -Noted that even when BIOSes do have VESA 2.0 built-in, it's often -so buggy that WinQuake crashes in faster configurations, and that -SciTech Display Doctor is the easiest way to get reliable VESA -support. - -Added note on Alt-Tab only working if Tab released first. - - -*** WinQuake 0.992 *** - -Implemented force_centerview. - -Fixed backspace bug in dedicated console. - -Made "player entering game" messages and "say" messages visible -in dedicated console. - -Added description of -heapsize (how to change default memory -allocation). - -Added description of "net play pauses every few seconds" bug. - -Added description of "playdemo fails across multiple levels" bug. - -Added hooks for QHost; however, WinQuake won't work with QHost -until a new version of QHost 3.0, which uses the hooks, is -released. QHost 3.0 will not work with WinQuake. - -Fixed bug where savegame descriptions weren't always terminated -properly. - -Fixed bug where running -dedicated reset part of config.cfg to -defaults. - - -*** WinQuake 0.991 *** - -Fixed problem with pre-1.07 (DOS) clients connecting to WinQuake. - -Got rid of "Starting Quake..." dialog when running -dedicated. - -Added -novbeaf switch to turn off VBE/AF support in case of problems, -and updated documentation. - -Corrected SciTech's U.S. Mail address in documentation. - -Added joystick bug decriptions and workarounds. - - - ------------------- -| Special thanks | ------------------- - -Special thanks for help with WinQuake to: - -James Barnes -Kendall Bennett -Raymond Chen -John Colleran -Andrew Goossen -Mike Harrington -Chris Hecker -Todd Laney -Scott Ludwig -...and all the beta testers! - -====================================================================== -End of Document 3/21/97 -====================================================================== +-------------------------- +| wqreadme.txt | +| WinQuake documentation | +| 3/21/97 | +-------------------------- + +WinQuake (WQ) is a native Win32 version of Quake, and will run on +either Win95 or Windows NT 4.0 or later. It is designed to take +advantage of whatever enhanced video, sound, and input capabilities +(such as DirectX or VESA VBE video modes) are present, but has +fallback functionality so it can run on any Win95 or NT 4.0 or later +system, even if neither DirectX nor VESA VBE is available. You may +experience problems running WQ on some systems, because driver and +operating-system support for game functionality are not yet mature +under Win32, and many bugs and incompatibilities remain in those +components. If you encounter what seems to be a bug, first please +check through the list of known problems, below. If your problem +doesn't appear on the list, please fill out and submit the WQ bug +report at http://www.idsoftware.com/contact/. + +The material accompanying Quake is the reference for all +non-Windows-related matters concerning WinQuake; in terms of gameplay, +WQ is the same as Quake. This file contains Windows-related +information only. + +The rest of this document is organized as follows: + +Installing and running WinQuake +Common problems and workarounds +A bit about how WQ video works +Video command-line switches +A bit about how WQ sound works +Sound command-line switches +Notes on networking +Notes on the mouse +Log of changes to documentation +Special thanks + + +----------------------------------- +| Installing and running WinQuake | +----------------------------------- + +In order to run WinQuake, you must first have Quake installed. +Assuming Quake is installed in the standard directory, c:\quake, +unzip the WinQuake zip file into c:\quake. The following files +from the zip file must be present in order for WQ to run: + +winquake.exe +pmpro16.dll +pmpro32.dll +wdir16.dll +wdir32.dll +wdirnop.com +wdirnop.pif + +Then you can run WinQuake by making c:\quake the current directory, +typing "winquake" and pressing the Enter key. Alternatively, you can +use wq.bat to run WinQuake. The wq batch file requires one parameter +describing how to configure WQ for performance; just type "wq" to get +a list of the six options. The first of the six options is + +wq fast + +This is the same as typing "winquake"; this runs WinQuake in an +aggressive configuration that is likely to yield the best performance +if it runs successfully on your system, but which has a risk of +causing WinQuake or even your system to crash if there are bugs or +incompatibilities in your video or sound drivers. Alternatively, you +can use + +wq safe + +to run WinQuake in a conservative configuration, likely to run +on almost all machines with no problems, but possibly with slower +graphics, fewer high-resolution modes, and delayed sound. Or you +can run + +wq verysafe + +to run WinQuake in a very conservative configuration that is pretty +much guaranteed to run, but will probably have slow performance, and +will have no sound. Two other options are + +wq fastvid + +which has maximum video performance, but greater sound latency (delay +until the sound is heard), and + +wq fastsnd + +which uses more conservative video modes, but low-latency sound. + +(One odd note is that DirectSound has much lower-latency sound than +wave sound, but is currently quite a bit slower overall. Thus you +may find that "wq fastvid" is actually faster, by as much as 5-10%, +than "wq fast"; however, it may not feel faster, because the sound +will lag.) + +Finally, you can use + +wq max + +which is the same as wq fast, but turns on DirectInput, which +provides more responsive mouse control, but does not work properly +on all systems. + +Note that DirectX is not required for WQ to run, but WQ will +automatically take advantage of DirectSound and DirectDraw if they +are present. If DirectSound is not present, there will generally be +considerable sound latency (sound will become audible several hundred +milliseconds after the event that caused it). Note also that there +are currently no true DirectSound drivers for Windows NT, so WQ will +always run using wave output on NT, and will consequently have lagged +sound. See below for information about obtaining DirectX if you do +not have it. + +Note that VESA VBE modes aren't required for WQ to run, but WQ will +automatically make VESA modes available if they're present. Your BIOS +may already have VESA VBE 2.0 support built in, but most BIOSes +don't. Worse, some BIOSes do have VESA VBE 2.0 built-in, but have +buggy implementations, which may prevent you from being able to run +the faster configurations of WQ. An easy way to get reliable VESA 2.0 +support is by obtaining SciTech Display Doctor; see below for +further information. WQ can also use VBE/AF 1.0 and greater modes; +again, SciTech Display Doctor is the commonest way to get VBE/AF +support. + +Note that winquake -dedicated completely replaces the old winded +dedicated Win32 server, which is now obsolete. + +WinQuake normally uses half the physical memory in your system for its +heap, but not less than 8.5 Mb and not more than 16 Mb. You can +override this with "-heapsize n", where n is the amount of memory to +allocate for the heap, in Kb. + +To use the joystick, you must bring down the console by pressing the +tilde ('~') key, and type "joystick 1"; you can disable the +joystick with "joystick 0" at any time. The joystick setting +remains in effect for subsequent WinQuake sessions until changed, so +you only need to do joystick 1 once to enable the joystick. If the +joystick somehow causes problems that keep you from being able to run +WinQuake at all, you can start WinQuake -nojoy to complete disable the +joystick for that session. + + +----------------------------------- +| Common problems and workarounds | +----------------------------------- + +WQ crashes or won't run +----------------------- + +If WQ refuses to run or crashes on your system, try running +it using "wq safe" or "wq verysafe". Or you can use command-line +switches: + +winquake -nodirectdraw -nowindirect -wavonly + +This will almost certainly solve your problem; however, it may result +in lagged sound (a long delay from action to hearing the sound), may +result in fewer or slower high-res video modes, and the mouse may be +somewhat less responsive. If this does work, you can try removing +each of the command-line switches until you identify the one that +fixes the problem, thereby sacrificing as little functionality as +possible. + +If the above command line does not fix your problems, try: + +winquake -dibonly -nosound + +which forces WQ into silent operation with bare-bones video support +and no use of DirectInput for mouse input (the normal Windows mouse +APIs are used instead). Again, if this works, try removing switches +until you identify the needed one. + +Both of the above command lines are quick fixes. Often, the problem +is caused by outdated or buggy DirectX drivers or code, and can +frequently be completely fixed simply by installing the latest +Microsoft-supplied version of DirectX, which you may be able to find +on http://www.microsoft.com/mediadev/download/directx.exe, although +the availability and location of the DirectX file changes +periodically; note that at last check, this is a 3.4 Mb file. (Be +aware, though, that sometimes Microsoft's DirectX drivers don't +support features that the manufacturers' drivers do support, such as +display refresh rate control.) + +One known problem of this sort involves the current SB16 drivers from +Creative Labs, which cause WQ to crash on some machines. The +DirectSound drivers from Microsoft, available via the above-mentioned +URL, fix this problem. + +It can also sometimes help to get the latest Windows drivers for your +video adapter or sound card (although as the SB16 example indicates, +this is not always a good idea), and for video boards that have flash +BIOSes, it can sometimes help to get the latest BIOS upgrade. + + +How do I select fullscreen or windowed WQ operation? +---------------------------------------------------- +Check out WQ's new, spiffy Video menu, accessible from the Options +menu. There are now two types of modes listed, windowed and +fullscreen. You can make any of these modes the current and/or +default mode, just as in DOS Quake. If you make a windowed mode the +default, WQ will still briefly start up in fullscreen mode, then +switch to windowed; if this is a problem, use the -startwindowed +command-line switch. More complete video control is available +through the console, as described in the "A bit about how WQ video +works" section, below. + + +Gee, I wish I could use a mouse to play WQ with in a window +----------------------------------------------------------- +You can! While in a windowed mode, go to the Options menu. At the +bottom, you'll find a new selection that lets you choose to have the +mouse active when you're in a window. Of course, if you do this, +you'll have to use the keyboard (Alt-Tab, the Windows key, Ctrl-Esc, +Alt-Esc, or Shift-Alt-Tab) to switch away from WQ. + + +Serial/modem menu is missing +---------------------------- +WQ currently does not support direct connect serial or modem play. + + +DOS Quake reports unknown variables on startup after running WQ +--------------------------------------------------------------- +WQ uses some console variables that do not exist in DOS Quake, and +some of these are automatically archived in config.cfg when you exit +WQ. If you then start DOS Quake, DOS Quake will complain that it +doesn't recognize those variables. You will also lose the settings +of these variables when you return to WQ. Apart from losing the +settings, this is harmless; ignore it. + + +Problems running WQ on NT 3.51 +------------------------------ +NT 3.51 isn't supported by WQ. + + +WQ crashes while switching modes or Alt-Tabbing +----------------------------------------------- +So far, all cases of this seem to be tied to Creative Lab's SB16 sound +drivers, and have been fixed by getting the latest DirectX drivers, as +described above. Alternatively, you should be able to fix this either +by not switching modes or Alt-Tabbing, or by running -wavonly to +disable DirectSound support. + + +WQ sometimes runs pretty slowly fullscreen +------------------------------------------ +There are several possible reasons for this, starting with "You have a +slow computer." Assuming that's not the case, if you don't have +either DirectDraw or SciTech Display Doctor installed (see the "A bit +about how WQ video works" section), it would probably be a good thing +to install one or the other, because slow operation can be a result +of slow copying or stretching of pixels to the screen by a Windows +driver, something that's eliminated by both DirectDraw and Display +Doctor. You can also sometimes get a faster 320x200 mode on Win95 by +doing vid_describemodes, then using vid_mode to select a non-VGA +320x200 mode, as described in the "A bit about how WQ video works" +section. + +You can also try using a primary sound buffer on Win95 (this doesn't +work on NT) by using the -primarysound command-line switch; this can +improve performance by several percent, but does not work on all +systems, and can result in odd sound effects on some systems when +minimizing WQ or switching the focus away from it. If you use this +switch, please don't report sound bugs; it's in there purely for you +to use if it helps you, and we know it has problems on many systems. +Finally, you can use -wavonly to select wave sound; this will increase +your sound latency (sounds will be heard later than they should), but +allows WQ to run 5-10% faster on some systems. That's about all you +can do to speed up fullscreen WQ on Win95, other than shrinking the +active area of the screen with the screen size control in the Options +menu. + +NT 4.0 comes with DirectX installed, but doesn't have any resolutions +lower than 640x480. In order to support a lower-resolution 320x240 +mode, WQ has NT double each pixel in both directions to get enough +pixels for 640x480. The extra stretching costs some performance, the +result being that NT can seem sluggish on all but high-end Pentiums +and Pentium Pros. (In fact, depending on the quality of your driver's +stretching code, it can sometimes be faster to run WQ at 640x480 than +320x240-stretched on NT.) One thing that can help on NT is switching +to 640x480, then using the Options menu to shrink the active area of +the screen. + +A common cause of slowness running in a window is having the desktop +run in 16- or 32-bpp mode. WQ is an 8-bpp application, and it slows +things down if pixels have to be translated from 8-bpp to 16- or +32-bpp. (Note that this is generally a problem only when running in a +window; fullscreen apps rarely suffer from this.) + + +Sound is sluggish on NT +----------------------- +NT doesn't have any real DirectSound drivers yet, so there's no way to +do quick-response sound on NT. When DirectSound drivers for NT +appear, WQ's sound should automatically be snappier. + + +Sound breaks up or gets choppy, especially in menus +--------------------------------------------------- +This is generally a sign that WQ's frame rate is too low on your +system. Try reducing resolution or shrinking the active area of the +screen. In some circumstances, it may help to set the console +variable _snd_mixahead to a larger value. + + +The color black doesn't change with palette flashes sometimes +------------------------------------------------------------- +Normally, DirectDraw lets WQ change all 256 colors, so when a palette +flash happens, we can change all the colors, including black. +However, on NT DirectDraw currently doesn't allow changing black; +likewise, on both NT and Win95, black can't be changed in a window, +either a normal window or fullscreen. Consequently, in some modes and +in a window, some parts of the WQ screen (such as the sigils on the +status bar and the spray where a shotgun blast hits) stay black when +the palette flashes. There is no workaround. + + +Problems can result if Office shortcut bar is running +----------------------------------------------------- +Various odd behaviors, especially with sound, have been reported if +the Office shortcut bar is running while WQ is running. If you +experience odd problems, you might try shutting down the Office +shortcut bar and see if that fixes anything. + + +Other apps fail to play sound while WinQuake is running +------------------------------------------------------- +The sound hardware is currently not a fully shareable resource on +Win32. Consequently, while WQ is running, it always has the sound +hardware allocated to itself, to make sure that sound is never lost to +another app. This means that normally (when WQ is using DirectSound), +apps that use wave sound (most non-game apps) will not be able to play +sound while WQ is running, even if WQ is minimized or not the active +app, although other DirectSound apps will be able to play sound when +WQ is not the active app. If WQ is using wave sound rather than +DirectSound (either because -wavonly is used on the command line, or +because there is no DirectSound driver, as is always the case on NT), +then no other app will be able to play any sound while WQ is running, +period. + + +WQ doesn't have quite the right colors when it’s not the active app +------------------------------------------------------------------- +We're working on fixing this. But WQ puts everything back again as +soon as it is reactivated, and anyway, when it’s not active, you can’t +actually do anything in WQ, so it doesn’t really matter anyway, right? + + +Desktop is weird colors when WQ runs windowed +--------------------------------------------- +WQ needs all 256 colors to look right and run fast, which causes it to +have to change some of the 20 colors used to draw the desktop. + + +Sometimes Permedia boards crash unless -nowindirect is used +----------------------------------------------------------- +It looks like this is probably a Permedia driver bug, so it might help +if you get the most recent drivers. + + +Right-click on WQ button in task bar to close doesn’t work as expected +---------------------------------------------------------------------- +In some modes, right-clicking on the WQ task bar button doesn't work +the way you'd expect. We're trying to fix this, but if it's a +problem, don't right-click. + + +Screen saver never kicks in when running WQ fullscreen +------------------------------------------------------ +It does work windowed, but when WinQuake is fullscreen, it completely +owns the screen and doesn't share it with anyone, even the +screensaver. If you use Alt-Tab to minimize WQ, the screensaver will +then be enabled, so Alt-Tab away from WQ if you're leaving your +computer alone for a while and want the screensaver to be able to kick +in. + + +WQ doesn’t work in a window in 16-color mode +-------------------------------------------- +That’s 16 *colors*, not 16-bpp. If you’re still running a 16-color +desktop, run WQ fullscreen. + + +Can't minimize window while mouse active +---------------------------------------- +When running in a window with the mouse active as a WQ input device, +there is no easy way to minimize the window, because the system menu +can't be brought up from the keyboard (because some of you use Alt +and Spacebar for playing the game), and the mouse can't be used to +manipulate the window because it's controlling WQ. To minimize, you +can disable the mouse for WQ and use it to minimize the window. Or +on Win95 you can Alt-Tab away from WQ, then use the mouse to +minimize (this doesn't work on NT, where clicking on the window +controls just reactivates WQ). Or you can bind a key to the +vid_minimize command, as in + +bind m "vid_minimize" + +and press that key to minimize the window. + + +Window controls don't work on NT when mouse enabled +--------------------------------------------------- +When running in a window on NT with the mouse enabled (so you can use +the mouse to play WQ), if you Alt-Tab away from WQ, then use the mouse +to click on the WQ system menu control, or the minimize, maximize, or +close controls, the controls are ignored and WQ just reactivates. + + +Mouse sometimes vanishes in system menu on Win95 +------------------------------------------------ +On Win95, if WQ is running in a window with the mouse enabled (so you +can use the mouse to play WQ), if you Alt-Tab away, then click on the +system menu, the menu comes up, but the mouse vanishes. However, you +can still use the keyboard to select system menu items, or to exit +the system menu. + + +WQ behaves oddly if Scandisk starts defragmenting +------------------------------------------------- +If WQ is running fullscreen on Win95 when Scandisk starts an automatic +defragging, WQ is forced to minimize, and when it is brought back up, +may either be in a strange mode where it runs one frame for each +keystroke (in which case Alt-Tab generally fixes things), or may hang +the system. We don't know what the problem is right now, but you may +want to make sure you don't leave WQ sitting there fullscreen +overnight if you have automatic defragging. + + +Hang reported with zero sound volume +------------------------------------ +When sound is turned all the way down via the WQ menus, hangs have +been reported. + + +Joystick worked fine with earlier versions of WinQuake but not now +------------------------------------------------------------------ +The joystick was enabled by default in earlier versions of +WinQuake, but quite a few people reported serious problems that +forced them to disable the joystick--even some people who didn't +have a joystick attached. Since most people don't have joysticks, +we've decided to disable the joystick by default, and let people +who do want to use it set joystick 1 in the console (WinQuake +remembers this setting, so this only needs to be done once). + + +WQ runs very slowly when it has the focus under NT +-------------------------------------------------- +In one case, WQ ran very slowly when it had the focus, but fast when +it didn't (obviously this is only visible in windowed modes). The +problem turned out to be that NT had a Sidewinder 3D Pro joystick +driver installed; when the driver was removed, things were fine. +If you see a similar problem, check whether WQ is detecting that +your system has a joystick when you don't think it should; if so, +try doing "joystick 0", or -nojoy on the command line, and see if +that fixes it. If so, there's something flaky in your system +joystick setup. + + +Joystick doesn't seem calibrated properly +----------------------------------------- +WQ relies on the information about your joystick stored in the +system registry. If the joystick seems miscalibrated, run the +joystick applet and recalibrate and see if that fixes things. + + +Playdemo fails across multiple levels +------------------------------------- +If "record" is used to record a client-side demo, bad things will +happen on playback via playdemo if a level change is recorded. +(Timedemo works fine.) This is unfortunate, but WinQuake +internals make this not fixable without a good chance of +breaking something more important, so it'll have to stay this way. + + +Alt-Tab fullscreen only works sometimes +--------------------------------------- +I know it seems that way, but actually the trick is that on Win95 +it only works if you let go of Tab before you let go of Alt. +This is due to a Windows quirk involving what key sequences are +passed along, so you'll have to work around it by remembering to +let go of Tab first. + + +MS-DOS windows get scrunched on Alt-Tab +--------------------------------------- +This is a quirk of Windows; when you run WinQuake in a low-res +mode, sometimes when you exit WinQuake or Alt-Tab back to the +desktop, any open MS-DOS windows will be scrunched down to the +size of the low-res mode. There is no known workaround. + + +Dprint in progs doesn't work +---------------------------- +Dprint means "developer print," so it only works if the developer +console variable is set to 1. It was a bug in earlier versions that +it worked even when developer was set to 0. + + +Some DirectDraw modes flicker badly and look wrong +-------------------------------------------------- +Page flipping doesn't work properly in some modes on some +systems, particularly when using some DirectDraw modes. You +can work around this by setting the console variable +vid_nopageflip to 1, then setting the desired mode (note +that the vid_nopageflip setting does not take effect until +the next mode set after the setting is changed). Bear in +mind, though, that the vid_nopageflip setting is remembered +until it is explicitly changed again, meaning that once you +change it, it thereafter applies to all modes, even if you +exit and restart WinQuake. + + +The Windows key doesn't do anything fullscreen on Win95 +------------------------------------------------------- +True. This is a minor bug we haven't figured out how to fix yet. +You'll have to use Ctrl-Esc, Alt-Tab, or Alt-Esc to switch away. + + +My default mode is windowed, but WQ goes fullscreen first +--------------------------------------------------------- +For internal reasons, WQ has to pick a single mode to always +initialize when it starts up, before it sets whatever default you've +selected. We've chosen fullscreen mode, because that's the way most +people will play. If this is a problem for you, however, you can +run WQ with the -startwindowed command-line parameter. + + +Some high-resolution video modes flicker or fail to initialize +-------------------------------------------------------------- +We think these problems are all fixed, but if not, they have to +do with triple-buffering in some modes on some DirectDraw drivers. +If you encounter this problem, either don't use the problem modes +or try using the -notriplebuf command-line parameter to turn off +triple buffering. Note, though, that turning off triple-buffering +can reduce performance in some modes, so do this only if needed. + + +Right-click doesn't work right on minimized WinQuake +---------------------------------------------------- +If you right-click on minimized WinQuake on the task bar, the +Close selection in the right-click menu doesn't work; you have +to restore WQ before you can exit it. Also, the cursor vanishes +over the right-click menu, although it still works. + + +The screen briefly blanks when you exit WQ +------------------------------------------ +We're trying to fix this, but it's not harmful, just a mite ugly. + + +QBENCH doesn't work with WinQuake +--------------------------------- +We've had a report that QBENCH doesn't work with WinQuake, but +haven't had a chance to look into it yet. + + +MWAVE sound loses focus +----------------------- +We've had a report that on a ThinkPad with MWAVE sound, WQ loses +sound focus (and thus sound) every few seconds. + + +Desktop doesn't reset to proper resolution on WQ exit +----------------------------------------------------- +We've had a report that on exiting WQ, the desktop didn't reset +to the proper dimensions. This may be a bug with the Matrox +drivers, but we're not sure. If it's a problem and newer +drivers don't fix it, you can run -dibonly, which solves the +problem but can cost some performance. + + +Palette goes bad periodically on #9 Imagine card +------------------------------------------------ +There's only one report of this, so maybe it's a flaky board, +or maybe it's a driver bug. Newer drivers might help. + + +System with Packard Bell sound card III crashes on CapsLock +----------------------------------------------------------- +This appears to be the result of buggy DirectSound drivers; +-wavonly makes the problem go away. + + +Dvorak keyboard mapping ignored +------------------------------- +WQ is hardwired for QWERTY. + + +Cursor messed up after running WQ +--------------------------------- +This is a Windows driver bug; the driver isn't restoring the +cursor properly on return from fullscreen WQ to the desktop. +Try newer drivers. + + +Dedicated server runs very slowly while typing at console +--------------------------------------------------------- +When you type at a dedicated server's console, the game runs +very slowly for everyone who's connected. + + +Ctrl-Alt-Del on NT sometimes doesn't allow return to WQ +------------------------------------------------------- +This happens on some machines while running WQ fullscreen. +If you experience this problem, the only workaround is not +to press Ctrl-Alt-Del while fullscreen; Alt-Tab away first. + + +Many fast Alt-Tabs on Win95 sometimes disable WQ input +------------------------------------------------------ +If you Alt-Tab fast lots of times on Win95 with WQ running +fullscreen, sometimes you end up in fullscreen WQ, with the +game not accepting any keyboard input (so there's no way to +exit). The only workaround is to not do lots of fast +Alt-Tabs (why you'd want to, I'm not sure). + + + +---------------------------------- +| A bit about how WQ video works | +---------------------------------- + +WQ has the built-in ability to draw into windows (both normal, framed +desktop windows and fullscreen, borderless windows). It also has +built- in support for VGA 320x200 graphics, and supports DirectDraw, +VESA VBE 2.0 and VESA VBE/AF (Accelerator Functions) graphics modes, +if those are available. + +WQ does not require DirectDraw, but in order for DirectDraw modes to +be available, you must have DirectDraw installed; some systems come +with it preinstalled, but if it's not on your system, you can download +it from http://www.microsoft.com/mediadev/download/directx.exe (the +exact URL may vary), and install it. + +WQ does not require VESA VBE, but in order for VESA VBE modes to be +available, your graphics card must be VESA VBE 2.0 or VBE/AF +compliant; a VESA driver can either be built into the BIOS of your +graphics card, or loadable via software. If you don't have a VESA VBE +driver, Scitech Display Doctor, available from Scitech Software, will +update most graphics cards to VESA VBE 2.0 and VBE/AF. + + +SciTech Display Doctor +---------------------- +If you are having problems with your video drivers, or if you would +like to take a shot at improving your video performance in WQ, you may +want to try out SciTech Display Doctor (SDD). SDD works on just about +any graphics card and it can do several things that can make WQ run +better on your system: + +1. It will update your graphics card to be compatible with VESA VBE +2.0 and VESA VBE/AF (Accelerator Functions). These modes will usually +give you the best performance in WQ (which is often but not always +faster than your current performance). + +2. It creates low-resolution modes on your graphics card. +Low-resolution video modes (such as 320x240, 400x300 and 512x384) +allow you to adjust the level of detail in WQ so you can get the best +balance between performance and image quality. + +The latest version of SciTech Display Doctor can be obtained from the +following locations: + +www: http://www.scitechsoft.com +ftp: ftp.scitechsoft.com +CIS: GO SCITECH +AOL: Keyword SciTech + +SciTech can be contacted at: + +email: info@scitechsoft.com + +SciTech Software, Inc. +505 Wall Street +Chico, CA 95926-1989 +916-894-8400 +916-894-9069 FAX + + +Video modes supported in Win95 +------------------------------ +What all this means is that on Win95, WQ will always be able to run in +the following modes: + +1) in a window +2) fullscreen 320x200 VGA mode 0x13 +3) fullscreen high-resolution of some sort + +Category #3 can be any of several configurations. On Win95, if either +DirectDraw or VESA VBE modes are available, then all the DirectDraw +and VESA modes will be presented as high-res choices. (320x200 will +always default to VGA mode 0x13.) In the case that a given resolution +is supported by both DirectDraw and VESA, the VESA mode will be used. +(However, the command-line switch -nowindirect can turn off VESA modes +entirely.) If neither DirectDraw nor VESA modes are available, then +high-resolution modes will be provided by using fullscreen, borderless +windows in whatever resolutions the Windows driver supports, usually +starting at 640x480 and going up. + + +Video Modes Supported in Windows NT +----------------------------------- +NT is similar but not identical, because neither VESA VBE modes nor +VGA mode 0x13 are available. On NT, WQ will always be able to run in +the following modes: + +1) in a window +2) fullscreen high-resolution of some sort + +On NT, category #2 can be one of two configurations. If DirectDraw +modes are available, then those will be the high-res choices; +otherwise, fullscreen, borderless windows will be used in whatever +resolutions the driver supports, usually starting at 640x480 and going +up. Because there is normally no low-resolution mode such as 320x200 +or 320x240 on NT, a pseudo low-res mode is created by rendering at +320x240, then stretching the image by doubling it in each direction +while copying it to a 640x480 screen. However, stretching performance +depends on the driver, and can be slow, so sometimes 640x480 is +actually faster than 320x240 on NT. + +The bottom line here is that you can generally just use the Video menu +and pick one of the modes and be happy. In some cases, though, you +may need to use command-line switches (described next) to get the +types of modes you want. One useful tip is to go into the console and +do vid_describemodes, which lists all the modes WQ makes available on +your machine given the command-line switches you've used. Each mode +is followed by the name of the internal WQ driver that supports it, so +you can tell which modes are DirectDraw, VESA, and so on, as follows: + +WINDOWED: WQ runs in a normal window +FULLSCREEN DIB: fullscreen borderless window +FULLSCREEN VGA8.DRV: VGA 320x200 mode +FULLSCREEN DDRAW8.DRV: DirectDraw mode +FULLSCREEN LINEAR8.DRV: VESA VBE 2.0+ mode +FULLSCREEN ACCEL8.DRV: VESA VBE/AF (Accelerator Functions) mode + (note that WQ does not take advantage of + VBE/AF acceleration; so far as WQ is + concerned VBE/AF is the same as normal VBE) + +You can use vid_mode from the console to set any of these modes. So, +for example, if you see that there are two 320x200 modes (such as one +VGA mode 0x13, normally mode 3, and one VESA mode, normally mode 4), +you can choose the VESA mode, which will often be faster, with +vid_mode 4. (You can make it the default by setting +_vid_default_mode_win to the mode number.) + +There's more to the windowed modes than you might think. 320x240 is +just what you’d expect, but 640x480 is actually rendered at 320x240 +and stretched up to 640x480, because most machines can’t handle the +performance demands of real 640x480 rendering. Likewise, 800x600 is a +stretched 400x300. Actually, though, vid_mode 2 (the 800x600 mode) is +a user-configurable mode. By setting the following console variables, +you can change the characteristics of vid_mode 2: + +vid_config_x: width of mode 2 window + +vid_config_y: height of mode 2 window + +vid_stretch_by_2: whether to render at half-resolution in each +direction and stretch up to the specified size in mode 2, or render at +full resolution. + +After setting these variables in the console, do a vid_forcemode 2, +and you’ll have the window you specified. Note that after making +these changes, the new resolution will show up as the third windowed +mode in the Video menu. + +If you don't have WQ mouse play enabled in windowed mode, you can also +go from windowed to fullscreen mode simply by clicking on the maximize +button. The mode switched to is controlled by the vid_fullscreen_mode +console variable, and defaults to mode 3. + +Other video console commands include: + +vid_fullscreen: switch to the mode specified by the +vid_fullscreen_mode console variable. + +vid_windowed: switch to the mode specified by the vid_windowed_mode +console variable. + +Vid_fullscreen and vid_windowed can be bound to keys, so it's possible +to flip between windowed and fullscreen with a single key press. + +Also, vid_minimize minimizes the WinQuake window if and only if +WinQuake is running in a windowed mode. You can bind a key to +the commands "vid_windowed; wait; vid_minimize" to minimize WQ +regardless of whether you're running in windowed or fullscreen mode. + +You can turn off page flipping by setting the console variable +vid_nopageflip to 1, then setting a new mode. (Note that the +vid_nopageflip setting does not take effect until the next mode set.) +Some systems run faster with page flipping turned off; also, page +flipping does not work properly on some adapters, and vid_nopageflip +is a workaround for this. Note that vid_nopageflip is a persistent +variable; it retains its setting until it is explicitly changed again, +even across multiple WinQuake sessions. + +The vid_forcemode console command sets the specified mode, even if +it's the same as the current mode (normally the mode set only happens +if the new mode differs from the current mode). This is generally +useful only if you've modified the characteristics of video mode 2 +(the configurable window) while you're in mode 2, and want to force +the new characteristics to take effect. + +Whenever you switch to running WinQuake in a window, the window is +placed at the same location it was in the last time WinQuake ran +in a window. You can reset the window position to the upper left +by using the -resetwinpos command-line switch. The window position +is stored in the vid_window_x and vid_window_y console variables. + + + +------------------------------- +| Video command-line switches | +------------------------------- + +The full list of video-related command-line switches is: + +-dibonly: WQ will use only windows (both normal, framed windows on the +desktop and fullscreen, borderless windows), not any direct hardware +access modes such as DirectDraw or VESA modes, or even VGA 320x200 +mode. This is the closest thing to a guaranteed-to-run fullscreen +mode WQ has. + +-nowindirect: WQ will not try to use VESA VBE 2.0 modes, or VBE/AF +1.0 or later modes. Note that if there are both DirectDraw and VESA +modes for a given resolution, WQ will normally use the VESA mode; +-nowindirect allows DirectDraw modes to be the preferred choice for +all resolutions except 320x200. This can be useful if WQ is crashing +because of a buggy VESA driver. + +-nodirectdraw: WQ will not try to use DirectDraw modes. This can be +useful if WQ is crashing because of a buggy DirectDraw driver. + +-novbeaf: WQ will not try to use VBE/AF 1.0 or later modes. + +-startwindowed: WQ will come up in a windowed mode, without going +fullscreen even during initialization. + +-noforcevga: normally, WQ uses VGA mode 0x13 for the default 320x200 +mode, even if a DirectDraw or VESA 320x200 mode exists. However, +DirectDraw and VESA modes can be considerably faster than mode 0x13, +because they can set up a linear framebuffer with higher memory +bandwidth. If you specify -noforcevga, the default 320x200 mode in +the menu will be a DirectDraw or VESA mode if one exists. This has no +effect on modes selected via the console variable vid_mode, and if +320x200 is already your video mode, -noforcevga doesn't do anything +until you use the menu to select another mode, then select 320x200 +again. (So if your default mode is 320x200 and you then specify +-noforcevga, switch away to some other mode and then back to 320x200 +to get the potentially faster 320x200 mode.) The downside to this +switch is that DirectDraw and VESA modes can cause problems in some +systems, due to driver bugs or hardware incompatibilities; if you +experience problems with this switch, don't use it. + +-noautostretch: don't stretch windowed modes selected with +-startwindowed to double resolution. + +-nofulldib: don't use fullscreen, borderless windows, even if there +are no DirectDraw or VESA modes available. + +-allow360: allow listing of 360-wide modes in the video mode menu. +These are normally filtered out to make sure the menu doesn't get too +full, which could cause high-res modes not to be displayed. + +-notriplebuf: prevent triple-buffered page flipping (rather than double- +buffered). This may result in slower performance, but is a workaround +if you encounter problems with flicker or initialization failure, which +could possibly happen in some modes with some DirectDraw drivers. + + + +---------------------------------- +| A bit about how WQ sound works | +---------------------------------- + +WQ can use either DirectSound or Windows wave output to generate +sound. If DirectSound is available, it is used; if not, if wave sound +is available it is used; and if neither is available, there is no +sound. DirectSound results in the best sound quality, and also the +lowest-latency sound; use it if you can, because you will be happier +with the results. (Note, though, that no NT sound drivers yet support +DirectSound.) Wave sound will often have high latency, lagging the +events that generate sound by hundreds of milliseconds on some +machines. + +You can tell what kind of sound WQ uses on your system by looking at +the startup portion of the console; you will see either "DirectSound +initialized" or "Wave sound initialized" (neither message is printed +if there's no sound). Any sound failure messages will also be printed +in the startup portion of the console. + +Note that WQ generates sound only when it is the active app, the one +with the input focus. + + + +------------------------------- +| Sound command-line switches | +------------------------------- + +The full list of sound-related command-line switches is: + +-wavonly: don’t use DirectSound, but use wave sound if available. +Note that wave sound is generally faster than DirectSound, but has +considerably greater latency. This switch is redundant on NT, because +all sound output on current NT drivers is wave sound. + +-nosound: don’t output any sound. + +-primarysound: use DirectSound primary buffer output. This is +generally faster than normal secondary buffer output, but does not +work in some systems, and produces odd sound glitches on minimization +and focus switching in other systems. Use it at your own risk, and +please do not report sound bugs if you're using this switch. + +-snoforceformat: WQ will not try to force the sound hardware to 11 +KHz, 16 bits per sample. This may be useful if DirectSound is failing +for no apparent reason, but generally WQ will produce better sound and +better performance if this switch is not used. + + + +----------------------- +| Notes on networking | +----------------------- + +The winsock TCP/IP driver will not cause a dial-up internet connection +to automatically start up when Quake is started. If you start Quake +with it inactive, the connection will be activated when you either try +to connect to a server or search for local servers. + +The local IP address will not always be known at startup. If it is +currently unknown the menu will display "INADDR_ANY". This will be +replaced with the real address when it is known. The IP address will +become known when you try to connect to a server, you search for local +servers, or you start a server. + +For multi-homed machines (machines with more than one network adapter +and IP adress), you can force WinQuake to bind to a specific IP +address. There is a command line option "-ip" that takes an IP +address as its parameter. + + + +---------------------- +| Notes on the mouse | +---------------------- + +If DirectInput is installed and functioning, WinQuake can use it for +mouse input, but does not do so automatically because DirectInput does +not work properly on all systems. DirectInput can be enabled via the +command-line switch -dinput. If DirectInput is not available or is +not enabled, WinQuake uses the normal Windows mouse APIs instead. +DirectInput provides slightly smoother motion; also, it tends to be +more responsive to fast spinning motions, and we recommend that you use +it if it works properly on your system. You can determine if WQ uses +DirectInput on your system when you use -dinput by checking for +"DirectInput initialized" in the startup console text. If not, you +might try installing DirectX 3 (note, though, that as I write this +there is no released DirectInput support for Windows NT, only Win95). + + + +----------------------------------- +| Log of changes to documentation | +----------------------------------- + +*** WinQuake 0.994 *** + +Fixed bug where in some cases involving IPX, whenever a new person +entered the game, a current player got dumped. + +Added DirectInput mouse support, and the -dinput command-line to +enable it. + +Added -notriplebuf to disable triple buffering to work around +possible problems with some modes on some DirectDraw drivers. + +Added remembering last window position, and restoring that, rather +than centering the window, whenever WinQuake runs in a window. +Can be reset with the -resetwinpos command-line switch. + +Added the vid_minimize command, which minimizes WinQuake if and only +if the current mode is windowed. + +Made it so WinQuake no longer gets suspended when Alt-Tab is used to +switch away from a fullscreen session. The means you can Alt-Tab +away from fullscreen WinQuake without losing a connection to a +Quake server. + +Added vid_nopageflip console variable to turn off page flipping, and +documented page flipping problems this can be used to work around. + +Documented that Del-Ctrl-Alt (in that order) causes WinQuake to +fault on Win95. + +Fixed the winsock TCP/IP driver so it will not cause a dial-up +internet connection to automatically start up when Quake is started. +If you start Quake with the internet connection already active, there +will be no difference. If you start Quake with it inactive, the +connection will be activated when you either try to connect to a +server or search for local servers. + +The local IP address will not always be known at startup now. If it +is currently unknown the menu will display "INADDR_ANY". This +will be replaced with the real address when it is known. The IP +address will become known when: you try to connect to a server, +you search for local servers, or you start a server. + +For multi-homed machines (machines with more than one network +adapter and IP adress), you can now force WinQuake to bind to a +specific IP adress. There is a new command line option "-ip" that +takes an IP address as its parameter. + +Added vid_fullscreen_mode and ability to select that mode by +clicking on the maximize button. Added two commands: +vid_fullscreen to switch to vid_fullscreen_mode, and +vid_windowed to switch to vid_windowed mode. + +Changed joystick default to disabled; now it only works if the +joystick cvar is set to 1; however, this setting now remains in +effect permanently. Added joystick documentation below. + +Documented dprint only works if developer set to 1. + +Documented scrunching of MS-DOS windows on Alt-Tab. + +Documented that NT versions earlier to 4.0 are not supported. + +Added DirectInput support for devices such as First Person +Gaming's Assassin controller. All buttons should now +be configurable in WinQuake. + +Fixed bug where when low-res fullscreen DIB modes selected from +the menu sometimes ran very slowly or produced garbled displays. + +Fixed bug where 1.06 and earlier save files couldn't be loaded +by WinQuake. + +Removed "Net play pauses every few seconds" bug; it was determined +not to be a bug, just an artifact of network play. + +Noted that even when BIOSes do have VESA 2.0 built-in, it's often +so buggy that WinQuake crashes in faster configurations, and that +SciTech Display Doctor is the easiest way to get reliable VESA +support. + +Added note on Alt-Tab only working if Tab released first. + + +*** WinQuake 0.992 *** + +Implemented force_centerview. + +Fixed backspace bug in dedicated console. + +Made "player entering game" messages and "say" messages visible +in dedicated console. + +Added description of -heapsize (how to change default memory +allocation). + +Added description of "net play pauses every few seconds" bug. + +Added description of "playdemo fails across multiple levels" bug. + +Added hooks for QHost; however, WinQuake won't work with QHost +until a new version of QHost 3.0, which uses the hooks, is +released. QHost 3.0 will not work with WinQuake. + +Fixed bug where savegame descriptions weren't always terminated +properly. + +Fixed bug where running -dedicated reset part of config.cfg to +defaults. + + +*** WinQuake 0.991 *** + +Fixed problem with pre-1.07 (DOS) clients connecting to WinQuake. + +Got rid of "Starting Quake..." dialog when running -dedicated. + +Added -novbeaf switch to turn off VBE/AF support in case of problems, +and updated documentation. + +Corrected SciTech's U.S. Mail address in documentation. + +Added joystick bug decriptions and workarounds. + + + +------------------ +| Special thanks | +------------------ + +Special thanks for help with WinQuake to: + +James Barnes +Kendall Bennett +Raymond Chen +John Colleran +Andrew Goossen +Mike Harrington +Chris Hecker +Todd Laney +Scott Ludwig +...and all the beta testers! + +====================================================================== +End of Document 3/21/97 +====================================================================== diff --git a/WinQuake/zone.c b/WinQuake/zone.c index e30d7f8..42d7c45 100644 --- a/WinQuake/zone.c +++ b/WinQuake/zone.c @@ -1,935 +1,935 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// Z_zone.c - -#include "quakedef.h" - -#define DYNAMIC_SIZE 0xc000 - -#define ZONEID 0x1d4a11 -#define MINFRAGMENT 64 - -typedef struct memblock_s -{ - int size; // including the header and possibly tiny fragments - int tag; // a tag of 0 is a free block - int id; // should be ZONEID - struct memblock_s *next, *prev; - int pad; // pad to 64 bit boundary -} memblock_t; - -typedef struct -{ - int size; // total bytes malloced, including header - memblock_t blocklist; // start / end cap for linked list - memblock_t *rover; -} memzone_t; - -void Cache_FreeLow (int new_low_hunk); -void Cache_FreeHigh (int new_high_hunk); - - -/* -============================================================================== - - ZONE MEMORY ALLOCATION - -There is never any space between memblocks, and there will never be two -contiguous free memblocks. - -The rover can be left pointing at a non-empty block - -The zone calls are pretty much only used for small strings and structures, -all big things are allocated on the hunk. -============================================================================== -*/ - -memzone_t *mainzone; - -void Z_ClearZone (memzone_t *zone, int size); - - -/* -======================== -Z_ClearZone -======================== -*/ -void Z_ClearZone (memzone_t *zone, int size) -{ - memblock_t *block; - -// set the entire zone to one free block - - zone->blocklist.next = zone->blocklist.prev = block = - (memblock_t *)( (byte *)zone + sizeof(memzone_t) ); - zone->blocklist.tag = 1; // in use block - zone->blocklist.id = 0; - zone->blocklist.size = 0; - zone->rover = block; - - block->prev = block->next = &zone->blocklist; - block->tag = 0; // free block - block->id = ZONEID; - block->size = size - sizeof(memzone_t); -} - - -/* -======================== -Z_Free -======================== -*/ -void Z_Free (void *ptr) -{ - memblock_t *block, *other; - - if (!ptr) - Sys_Error ("Z_Free: NULL pointer"); - - block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); - if (block->id != ZONEID) - Sys_Error ("Z_Free: freed a pointer without ZONEID"); - if (block->tag == 0) - Sys_Error ("Z_Free: freed a freed pointer"); - - block->tag = 0; // mark as free - - other = block->prev; - if (!other->tag) - { // merge with previous free block - other->size += block->size; - other->next = block->next; - other->next->prev = other; - if (block == mainzone->rover) - mainzone->rover = other; - block = other; - } - - other = block->next; - if (!other->tag) - { // merge the next free block onto the end - block->size += other->size; - block->next = other->next; - block->next->prev = block; - if (other == mainzone->rover) - mainzone->rover = block; - } -} - - -/* -======================== -Z_Malloc -======================== -*/ -void *Z_Malloc (int size) -{ - void *buf; - -Z_CheckHeap (); // DEBUG - buf = Z_TagMalloc (size, 1); - if (!buf) - Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size); - Q_memset (buf, 0, size); - - return buf; -} - -void *Z_TagMalloc (int size, int tag) -{ - int extra; - memblock_t *start, *rover, *new, *base; - - if (!tag) - Sys_Error ("Z_TagMalloc: tried to use a 0 tag"); - -// -// scan through the block list looking for the first free block -// of sufficient size -// - size += sizeof(memblock_t); // account for size of block header - size += 4; // space for memory trash tester - size = (size + 7) & ~7; // align to 8-byte boundary - - base = rover = mainzone->rover; - start = base->prev; - - do - { - if (rover == start) // scaned all the way around the list - return NULL; - if (rover->tag) - base = rover = rover->next; - else - rover = rover->next; - } while (base->tag || base->size < size); - -// -// found a block big enough -// - extra = base->size - size; - if (extra > MINFRAGMENT) - { // there will be a free fragment after the allocated block - new = (memblock_t *) ((byte *)base + size ); - new->size = extra; - new->tag = 0; // free block - new->prev = base; - new->id = ZONEID; - new->next = base->next; - new->next->prev = new; - base->next = new; - base->size = size; - } - - base->tag = tag; // no longer a free block - - mainzone->rover = base->next; // next allocation will start looking here - - base->id = ZONEID; - -// marker for memory trash testing - *(int *)((byte *)base + base->size - 4) = ZONEID; - - return (void *) ((byte *)base + sizeof(memblock_t)); -} - - -/* -======================== -Z_Print -======================== -*/ -void Z_Print (memzone_t *zone) -{ - memblock_t *block; - - Con_Printf ("zone size: %i location: %p\n",mainzone->size,mainzone); - - for (block = zone->blocklist.next ; ; block = block->next) - { - Con_Printf ("block:%p size:%7i tag:%3i\n", - block, block->size, block->tag); - - if (block->next == &zone->blocklist) - break; // all blocks have been hit - if ( (byte *)block + block->size != (byte *)block->next) - Con_Printf ("ERROR: block size does not touch the next block\n"); - if ( block->next->prev != block) - Con_Printf ("ERROR: next block doesn't have proper back link\n"); - if (!block->tag && !block->next->tag) - Con_Printf ("ERROR: two consecutive free blocks\n"); - } -} - - -/* -======================== -Z_CheckHeap -======================== -*/ -void Z_CheckHeap (void) -{ - memblock_t *block; - - for (block = mainzone->blocklist.next ; ; block = block->next) - { - if (block->next == &mainzone->blocklist) - break; // all blocks have been hit - if ( (byte *)block + block->size != (byte *)block->next) - Sys_Error ("Z_CheckHeap: block size does not touch the next block\n"); - if ( block->next->prev != block) - Sys_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); - if (!block->tag && !block->next->tag) - Sys_Error ("Z_CheckHeap: two consecutive free blocks\n"); - } -} - -//============================================================================ - -#define HUNK_SENTINAL 0x1df001ed - -typedef struct -{ - int sentinal; - int size; // including sizeof(hunk_t), -1 = not allocated - char name[8]; -} hunk_t; - -byte *hunk_base; -int hunk_size; - -int hunk_low_used; -int hunk_high_used; - -qboolean hunk_tempactive; -int hunk_tempmark; - -void R_FreeTextures (void); - -/* -============== -Hunk_Check - -Run consistancy and sentinal trahing checks -============== -*/ -void Hunk_Check (void) -{ - hunk_t *h; - - for (h = (hunk_t *)hunk_base ; (byte *)h != hunk_base + hunk_low_used ; ) - { - if (h->sentinal != HUNK_SENTINAL) - Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size) - Sys_Error ("Hunk_Check: bad size"); - h = (hunk_t *)((byte *)h+h->size); - } -} - -/* -============== -Hunk_Print - -If "all" is specified, every single allocation is printed. -Otherwise, allocations with the same name will be totaled up before printing. -============== -*/ -void Hunk_Print (qboolean all) -{ - hunk_t *h, *next, *endlow, *starthigh, *endhigh; - int count, sum; - int totalblocks; - char name[9]; - - name[8] = 0; - count = 0; - sum = 0; - totalblocks = 0; - - h = (hunk_t *)hunk_base; - endlow = (hunk_t *)(hunk_base + hunk_low_used); - starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used); - endhigh = (hunk_t *)(hunk_base + hunk_size); - - Con_Printf (" :%8i total hunk size\n", hunk_size); - Con_Printf ("-------------------------\n"); - - while (1) - { - // - // skip to the high hunk if done with low hunk - // - if ( h == endlow ) - { - Con_Printf ("-------------------------\n"); - Con_Printf (" :%8i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used); - Con_Printf ("-------------------------\n"); - h = starthigh; - } - - // - // if totally done, break - // - if ( h == endhigh ) - break; - - // - // run consistancy checks - // - if (h->sentinal != HUNK_SENTINAL) - Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size) - Sys_Error ("Hunk_Check: bad size"); - - next = (hunk_t *)((byte *)h+h->size); - count++; - totalblocks++; - sum += h->size; - - // - // print the single block - // - memcpy (name, h->name, 8); - if (all) - Con_Printf ("%8p :%8i %8s\n",h, h->size, name); - - // - // print the total - // - if (next == endlow || next == endhigh || - strncmp (h->name, next->name, 8) ) - { - if (!all) - Con_Printf (" :%8i %8s (TOTAL)\n",sum, name); - count = 0; - sum = 0; - } - - h = next; - } - - Con_Printf ("-------------------------\n"); - Con_Printf ("%8i total blocks\n", totalblocks); - -} - -/* -=================== -Hunk_AllocName -=================== -*/ -void *Hunk_AllocName (int size, char *name) -{ - hunk_t *h; - -#ifdef PARANOID - Hunk_Check (); -#endif - - if (size < 0) - Sys_Error ("Hunk_Alloc: bad size: %i", size); - - size = sizeof(hunk_t) + ((size+15)&~15); - - if (hunk_size - hunk_low_used - hunk_high_used < size) - Sys_Error ("Hunk_Alloc: failed on %i bytes",size); - - h = (hunk_t *)(hunk_base + hunk_low_used); - hunk_low_used += size; - - Cache_FreeLow (hunk_low_used); - - memset (h, 0, size); - - h->size = size; - h->sentinal = HUNK_SENTINAL; - Q_strncpy (h->name, name, 8); - - return (void *)(h+1); -} - -/* -=================== -Hunk_Alloc -=================== -*/ -void *Hunk_Alloc (int size) -{ - return Hunk_AllocName (size, "unknown"); -} - -int Hunk_LowMark (void) -{ - return hunk_low_used; -} - -void Hunk_FreeToLowMark (int mark) -{ - if (mark < 0 || mark > hunk_low_used) - Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark); - memset (hunk_base + mark, 0, hunk_low_used - mark); - hunk_low_used = mark; -} - -int Hunk_HighMark (void) -{ - if (hunk_tempactive) - { - hunk_tempactive = false; - Hunk_FreeToHighMark (hunk_tempmark); - } - - return hunk_high_used; -} - -void Hunk_FreeToHighMark (int mark) -{ - if (hunk_tempactive) - { - hunk_tempactive = false; - Hunk_FreeToHighMark (hunk_tempmark); - } - if (mark < 0 || mark > hunk_high_used) - Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark); - memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark); - hunk_high_used = mark; -} - - -/* -=================== -Hunk_HighAllocName -=================== -*/ -void *Hunk_HighAllocName (int size, char *name) -{ - hunk_t *h; - - if (size < 0) - Sys_Error ("Hunk_HighAllocName: bad size: %i", size); - - if (hunk_tempactive) - { - Hunk_FreeToHighMark (hunk_tempmark); - hunk_tempactive = false; - } - -#ifdef PARANOID - Hunk_Check (); -#endif - - size = sizeof(hunk_t) + ((size+15)&~15); - - if (hunk_size - hunk_low_used - hunk_high_used < size) - { - Con_Printf ("Hunk_HighAlloc: failed on %i bytes\n",size); - return NULL; - } - - hunk_high_used += size; - Cache_FreeHigh (hunk_high_used); - - h = (hunk_t *)(hunk_base + hunk_size - hunk_high_used); - - memset (h, 0, size); - h->size = size; - h->sentinal = HUNK_SENTINAL; - Q_strncpy (h->name, name, 8); - - return (void *)(h+1); -} - - -/* -================= -Hunk_TempAlloc - -Return space from the top of the hunk -================= -*/ -void *Hunk_TempAlloc (int size) -{ - void *buf; - - size = (size+15)&~15; - - if (hunk_tempactive) - { - Hunk_FreeToHighMark (hunk_tempmark); - hunk_tempactive = false; - } - - hunk_tempmark = Hunk_HighMark (); - - buf = Hunk_HighAllocName (size, "temp"); - - hunk_tempactive = true; - - return buf; -} - -/* -=============================================================================== - -CACHE MEMORY - -=============================================================================== -*/ - -typedef struct cache_system_s -{ - int size; // including this header - cache_user_t *user; - char name[16]; - struct cache_system_s *prev, *next; - struct cache_system_s *lru_prev, *lru_next; // for LRU flushing -} cache_system_t; - -cache_system_t *Cache_TryAlloc (int size, qboolean nobottom); - -cache_system_t cache_head; - -/* -=========== -Cache_Move -=========== -*/ -void Cache_Move ( cache_system_t *c) -{ - cache_system_t *new; - -// we are clearing up space at the bottom, so only allocate it late - new = Cache_TryAlloc (c->size, true); - if (new) - { -// Con_Printf ("cache_move ok\n"); - - Q_memcpy ( new+1, c+1, c->size - sizeof(cache_system_t) ); - new->user = c->user; - Q_memcpy (new->name, c->name, sizeof(new->name)); - Cache_Free (c->user); - new->user->data = (void *)(new+1); - } - else - { -// Con_Printf ("cache_move failed\n"); - - Cache_Free (c->user); // tough luck... - } -} - -/* -============ -Cache_FreeLow - -Throw things out until the hunk can be expanded to the given point -============ -*/ -void Cache_FreeLow (int new_low_hunk) -{ - cache_system_t *c; - - while (1) - { - c = cache_head.next; - if (c == &cache_head) - return; // nothing in cache at all - if ((byte *)c >= hunk_base + new_low_hunk) - return; // there is space to grow the hunk - Cache_Move ( c ); // reclaim the space - } -} - -/* -============ -Cache_FreeHigh - -Throw things out until the hunk can be expanded to the given point -============ -*/ -void Cache_FreeHigh (int new_high_hunk) -{ - cache_system_t *c, *prev; - - prev = NULL; - while (1) - { - c = cache_head.prev; - if (c == &cache_head) - return; // nothing in cache at all - if ( (byte *)c + c->size <= hunk_base + hunk_size - new_high_hunk) - return; // there is space to grow the hunk - if (c == prev) - Cache_Free (c->user); // didn't move out of the way - else - { - Cache_Move (c); // try to move it - prev = c; - } - } -} - -void Cache_UnlinkLRU (cache_system_t *cs) -{ - if (!cs->lru_next || !cs->lru_prev) - Sys_Error ("Cache_UnlinkLRU: NULL link"); - - cs->lru_next->lru_prev = cs->lru_prev; - cs->lru_prev->lru_next = cs->lru_next; - - cs->lru_prev = cs->lru_next = NULL; -} - -void Cache_MakeLRU (cache_system_t *cs) -{ - if (cs->lru_next || cs->lru_prev) - Sys_Error ("Cache_MakeLRU: active link"); - - cache_head.lru_next->lru_prev = cs; - cs->lru_next = cache_head.lru_next; - cs->lru_prev = &cache_head; - cache_head.lru_next = cs; -} - -/* -============ -Cache_TryAlloc - -Looks for a free block of memory between the high and low hunk marks -Size should already include the header and padding -============ -*/ -cache_system_t *Cache_TryAlloc (int size, qboolean nobottom) -{ - cache_system_t *cs, *new; - -// is the cache completely empty? - - if (!nobottom && cache_head.prev == &cache_head) - { - if (hunk_size - hunk_high_used - hunk_low_used < size) - Sys_Error ("Cache_TryAlloc: %i is greater then free hunk", size); - - new = (cache_system_t *) (hunk_base + hunk_low_used); - memset (new, 0, sizeof(*new)); - new->size = size; - - cache_head.prev = cache_head.next = new; - new->prev = new->next = &cache_head; - - Cache_MakeLRU (new); - return new; - } - -// search from the bottom up for space - - new = (cache_system_t *) (hunk_base + hunk_low_used); - cs = cache_head.next; - - do - { - if (!nobottom || cs != cache_head.next) - { - if ( (byte *)cs - (byte *)new >= size) - { // found space - memset (new, 0, sizeof(*new)); - new->size = size; - - new->next = cs; - new->prev = cs->prev; - cs->prev->next = new; - cs->prev = new; - - Cache_MakeLRU (new); - - return new; - } - } - - // continue looking - new = (cache_system_t *)((byte *)cs + cs->size); - cs = cs->next; - - } while (cs != &cache_head); - -// try to allocate one at the very end - if ( hunk_base + hunk_size - hunk_high_used - (byte *)new >= size) - { - memset (new, 0, sizeof(*new)); - new->size = size; - - new->next = &cache_head; - new->prev = cache_head.prev; - cache_head.prev->next = new; - cache_head.prev = new; - - Cache_MakeLRU (new); - - return new; - } - - return NULL; // couldn't allocate -} - -/* -============ -Cache_Flush - -Throw everything out, so new data will be demand cached -============ -*/ -void Cache_Flush (void) -{ - while (cache_head.next != &cache_head) - Cache_Free ( cache_head.next->user ); // reclaim the space -} - - -/* -============ -Cache_Print - -============ -*/ -void Cache_Print (void) -{ - cache_system_t *cd; - - for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next) - { - Con_Printf ("%8i : %s\n", cd->size, cd->name); - } -} - -/* -============ -Cache_Report - -============ -*/ -void Cache_Report (void) -{ - Con_DPrintf ("%4.1f megabyte data cache\n", (hunk_size - hunk_high_used - hunk_low_used) / (float)(1024*1024) ); -} - -/* -============ -Cache_Compact - -============ -*/ -void Cache_Compact (void) -{ -} - -/* -============ -Cache_Init - -============ -*/ -void Cache_Init (void) -{ - cache_head.next = cache_head.prev = &cache_head; - cache_head.lru_next = cache_head.lru_prev = &cache_head; - - Cmd_AddCommand ("flush", Cache_Flush); -} - -/* -============== -Cache_Free - -Frees the memory and removes it from the LRU list -============== -*/ -void Cache_Free (cache_user_t *c) -{ - cache_system_t *cs; - - if (!c->data) - Sys_Error ("Cache_Free: not allocated"); - - cs = ((cache_system_t *)c->data) - 1; - - cs->prev->next = cs->next; - cs->next->prev = cs->prev; - cs->next = cs->prev = NULL; - - c->data = NULL; - - Cache_UnlinkLRU (cs); -} - - - -/* -============== -Cache_Check -============== -*/ -void *Cache_Check (cache_user_t *c) -{ - cache_system_t *cs; - - if (!c->data) - return NULL; - - cs = ((cache_system_t *)c->data) - 1; - -// move to head of LRU - Cache_UnlinkLRU (cs); - Cache_MakeLRU (cs); - - return c->data; -} - - -/* -============== -Cache_Alloc -============== -*/ -void *Cache_Alloc (cache_user_t *c, int size, char *name) -{ - cache_system_t *cs; - - if (c->data) - Sys_Error ("Cache_Alloc: allready allocated"); - - if (size <= 0) - Sys_Error ("Cache_Alloc: size %i", size); - - size = (size + sizeof(cache_system_t) + 15) & ~15; - -// find memory for it - while (1) - { - cs = Cache_TryAlloc (size, false); - if (cs) - { - strncpy (cs->name, name, sizeof(cs->name)-1); - c->data = (void *)(cs+1); - cs->user = c; - break; - } - - // free the least recently used cahedat - if (cache_head.lru_prev == &cache_head) - Sys_Error ("Cache_Alloc: out of memory"); - // not enough memory at all - Cache_Free ( cache_head.lru_prev->user ); - } - - return Cache_Check (c); -} - -//============================================================================ - - -/* -======================== -Memory_Init -======================== -*/ -void Memory_Init (void *buf, int size) -{ - int p; - int zonesize = DYNAMIC_SIZE; - - hunk_base = buf; - hunk_size = size; - hunk_low_used = 0; - hunk_high_used = 0; - - Cache_Init (); - p = COM_CheckParm ("-zone"); - if (p) - { - if (p < com_argc-1) - zonesize = Q_atoi (com_argv[p+1]) * 1024; - else - Sys_Error ("Memory_Init: you must specify a size in KB after -zone"); - } - mainzone = Hunk_AllocName (zonesize, "zone" ); - Z_ClearZone (mainzone, zonesize); -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Z_zone.c + +#include "quakedef.h" + +#define DYNAMIC_SIZE 0xc000 + +#define ZONEID 0x1d4a11 +#define MINFRAGMENT 64 + +typedef struct memblock_s +{ + int size; // including the header and possibly tiny fragments + int tag; // a tag of 0 is a free block + int id; // should be ZONEID + struct memblock_s *next, *prev; + int pad; // pad to 64 bit boundary +} memblock_t; + +typedef struct +{ + int size; // total bytes malloced, including header + memblock_t blocklist; // start / end cap for linked list + memblock_t *rover; +} memzone_t; + +void Cache_FreeLow (int new_low_hunk); +void Cache_FreeHigh (int new_high_hunk); + + +/* +============================================================================== + + ZONE MEMORY ALLOCATION + +There is never any space between memblocks, and there will never be two +contiguous free memblocks. + +The rover can be left pointing at a non-empty block + +The zone calls are pretty much only used for small strings and structures, +all big things are allocated on the hunk. +============================================================================== +*/ + +memzone_t *mainzone; + +void Z_ClearZone (memzone_t *zone, int size); + + +/* +======================== +Z_ClearZone +======================== +*/ +void Z_ClearZone (memzone_t *zone, int size) +{ + memblock_t *block; + +// set the entire zone to one free block + + zone->blocklist.next = zone->blocklist.prev = block = + (memblock_t *)( (byte *)zone + sizeof(memzone_t) ); + zone->blocklist.tag = 1; // in use block + zone->blocklist.id = 0; + zone->blocklist.size = 0; + zone->rover = block; + + block->prev = block->next = &zone->blocklist; + block->tag = 0; // free block + block->id = ZONEID; + block->size = size - sizeof(memzone_t); +} + + +/* +======================== +Z_Free +======================== +*/ +void Z_Free (void *ptr) +{ + memblock_t *block, *other; + + if (!ptr) + Sys_Error ("Z_Free: NULL pointer"); + + block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); + if (block->id != ZONEID) + Sys_Error ("Z_Free: freed a pointer without ZONEID"); + if (block->tag == 0) + Sys_Error ("Z_Free: freed a freed pointer"); + + block->tag = 0; // mark as free + + other = block->prev; + if (!other->tag) + { // merge with previous free block + other->size += block->size; + other->next = block->next; + other->next->prev = other; + if (block == mainzone->rover) + mainzone->rover = other; + block = other; + } + + other = block->next; + if (!other->tag) + { // merge the next free block onto the end + block->size += other->size; + block->next = other->next; + block->next->prev = block; + if (other == mainzone->rover) + mainzone->rover = block; + } +} + + +/* +======================== +Z_Malloc +======================== +*/ +void *Z_Malloc (int size) +{ + void *buf; + +Z_CheckHeap (); // DEBUG + buf = Z_TagMalloc (size, 1); + if (!buf) + Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size); + Q_memset (buf, 0, size); + + return buf; +} + +void *Z_TagMalloc (int size, int tag) +{ + int extra; + memblock_t *start, *rover, *new, *base; + + if (!tag) + Sys_Error ("Z_TagMalloc: tried to use a 0 tag"); + +// +// scan through the block list looking for the first free block +// of sufficient size +// + size += sizeof(memblock_t); // account for size of block header + size += 4; // space for memory trash tester + size = (size + 7) & ~7; // align to 8-byte boundary + + base = rover = mainzone->rover; + start = base->prev; + + do + { + if (rover == start) // scaned all the way around the list + return NULL; + if (rover->tag) + base = rover = rover->next; + else + rover = rover->next; + } while (base->tag || base->size < size); + +// +// found a block big enough +// + extra = base->size - size; + if (extra > MINFRAGMENT) + { // there will be a free fragment after the allocated block + new = (memblock_t *) ((byte *)base + size ); + new->size = extra; + new->tag = 0; // free block + new->prev = base; + new->id = ZONEID; + new->next = base->next; + new->next->prev = new; + base->next = new; + base->size = size; + } + + base->tag = tag; // no longer a free block + + mainzone->rover = base->next; // next allocation will start looking here + + base->id = ZONEID; + +// marker for memory trash testing + *(int *)((byte *)base + base->size - 4) = ZONEID; + + return (void *) ((byte *)base + sizeof(memblock_t)); +} + + +/* +======================== +Z_Print +======================== +*/ +void Z_Print (memzone_t *zone) +{ + memblock_t *block; + + Con_Printf ("zone size: %i location: %p\n",mainzone->size,mainzone); + + for (block = zone->blocklist.next ; ; block = block->next) + { + Con_Printf ("block:%p size:%7i tag:%3i\n", + block, block->size, block->tag); + + if (block->next == &zone->blocklist) + break; // all blocks have been hit + if ( (byte *)block + block->size != (byte *)block->next) + Con_Printf ("ERROR: block size does not touch the next block\n"); + if ( block->next->prev != block) + Con_Printf ("ERROR: next block doesn't have proper back link\n"); + if (!block->tag && !block->next->tag) + Con_Printf ("ERROR: two consecutive free blocks\n"); + } +} + + +/* +======================== +Z_CheckHeap +======================== +*/ +void Z_CheckHeap (void) +{ + memblock_t *block; + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + if (block->next == &mainzone->blocklist) + break; // all blocks have been hit + if ( (byte *)block + block->size != (byte *)block->next) + Sys_Error ("Z_CheckHeap: block size does not touch the next block\n"); + if ( block->next->prev != block) + Sys_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); + if (!block->tag && !block->next->tag) + Sys_Error ("Z_CheckHeap: two consecutive free blocks\n"); + } +} + +//============================================================================ + +#define HUNK_SENTINAL 0x1df001ed + +typedef struct +{ + int sentinal; + int size; // including sizeof(hunk_t), -1 = not allocated + char name[8]; +} hunk_t; + +byte *hunk_base; +int hunk_size; + +int hunk_low_used; +int hunk_high_used; + +qboolean hunk_tempactive; +int hunk_tempmark; + +void R_FreeTextures (void); + +/* +============== +Hunk_Check + +Run consistancy and sentinal trahing checks +============== +*/ +void Hunk_Check (void) +{ + hunk_t *h; + + for (h = (hunk_t *)hunk_base ; (byte *)h != hunk_base + hunk_low_used ; ) + { + if (h->sentinal != HUNK_SENTINAL) + Sys_Error ("Hunk_Check: trahsed sentinal"); + if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size) + Sys_Error ("Hunk_Check: bad size"); + h = (hunk_t *)((byte *)h+h->size); + } +} + +/* +============== +Hunk_Print + +If "all" is specified, every single allocation is printed. +Otherwise, allocations with the same name will be totaled up before printing. +============== +*/ +void Hunk_Print (qboolean all) +{ + hunk_t *h, *next, *endlow, *starthigh, *endhigh; + int count, sum; + int totalblocks; + char name[9]; + + name[8] = 0; + count = 0; + sum = 0; + totalblocks = 0; + + h = (hunk_t *)hunk_base; + endlow = (hunk_t *)(hunk_base + hunk_low_used); + starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used); + endhigh = (hunk_t *)(hunk_base + hunk_size); + + Con_Printf (" :%8i total hunk size\n", hunk_size); + Con_Printf ("-------------------------\n"); + + while (1) + { + // + // skip to the high hunk if done with low hunk + // + if ( h == endlow ) + { + Con_Printf ("-------------------------\n"); + Con_Printf (" :%8i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used); + Con_Printf ("-------------------------\n"); + h = starthigh; + } + + // + // if totally done, break + // + if ( h == endhigh ) + break; + + // + // run consistancy checks + // + if (h->sentinal != HUNK_SENTINAL) + Sys_Error ("Hunk_Check: trahsed sentinal"); + if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size) + Sys_Error ("Hunk_Check: bad size"); + + next = (hunk_t *)((byte *)h+h->size); + count++; + totalblocks++; + sum += h->size; + + // + // print the single block + // + memcpy (name, h->name, 8); + if (all) + Con_Printf ("%8p :%8i %8s\n",h, h->size, name); + + // + // print the total + // + if (next == endlow || next == endhigh || + strncmp (h->name, next->name, 8) ) + { + if (!all) + Con_Printf (" :%8i %8s (TOTAL)\n",sum, name); + count = 0; + sum = 0; + } + + h = next; + } + + Con_Printf ("-------------------------\n"); + Con_Printf ("%8i total blocks\n", totalblocks); + +} + +/* +=================== +Hunk_AllocName +=================== +*/ +void *Hunk_AllocName (int size, char *name) +{ + hunk_t *h; + +#ifdef PARANOID + Hunk_Check (); +#endif + + if (size < 0) + Sys_Error ("Hunk_Alloc: bad size: %i", size); + + size = sizeof(hunk_t) + ((size+15)&~15); + + if (hunk_size - hunk_low_used - hunk_high_used < size) + Sys_Error ("Hunk_Alloc: failed on %i bytes",size); + + h = (hunk_t *)(hunk_base + hunk_low_used); + hunk_low_used += size; + + Cache_FreeLow (hunk_low_used); + + memset (h, 0, size); + + h->size = size; + h->sentinal = HUNK_SENTINAL; + Q_strncpy (h->name, name, 8); + + return (void *)(h+1); +} + +/* +=================== +Hunk_Alloc +=================== +*/ +void *Hunk_Alloc (int size) +{ + return Hunk_AllocName (size, "unknown"); +} + +int Hunk_LowMark (void) +{ + return hunk_low_used; +} + +void Hunk_FreeToLowMark (int mark) +{ + if (mark < 0 || mark > hunk_low_used) + Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark); + memset (hunk_base + mark, 0, hunk_low_used - mark); + hunk_low_used = mark; +} + +int Hunk_HighMark (void) +{ + if (hunk_tempactive) + { + hunk_tempactive = false; + Hunk_FreeToHighMark (hunk_tempmark); + } + + return hunk_high_used; +} + +void Hunk_FreeToHighMark (int mark) +{ + if (hunk_tempactive) + { + hunk_tempactive = false; + Hunk_FreeToHighMark (hunk_tempmark); + } + if (mark < 0 || mark > hunk_high_used) + Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark); + memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark); + hunk_high_used = mark; +} + + +/* +=================== +Hunk_HighAllocName +=================== +*/ +void *Hunk_HighAllocName (int size, char *name) +{ + hunk_t *h; + + if (size < 0) + Sys_Error ("Hunk_HighAllocName: bad size: %i", size); + + if (hunk_tempactive) + { + Hunk_FreeToHighMark (hunk_tempmark); + hunk_tempactive = false; + } + +#ifdef PARANOID + Hunk_Check (); +#endif + + size = sizeof(hunk_t) + ((size+15)&~15); + + if (hunk_size - hunk_low_used - hunk_high_used < size) + { + Con_Printf ("Hunk_HighAlloc: failed on %i bytes\n",size); + return NULL; + } + + hunk_high_used += size; + Cache_FreeHigh (hunk_high_used); + + h = (hunk_t *)(hunk_base + hunk_size - hunk_high_used); + + memset (h, 0, size); + h->size = size; + h->sentinal = HUNK_SENTINAL; + Q_strncpy (h->name, name, 8); + + return (void *)(h+1); +} + + +/* +================= +Hunk_TempAlloc + +Return space from the top of the hunk +================= +*/ +void *Hunk_TempAlloc (int size) +{ + void *buf; + + size = (size+15)&~15; + + if (hunk_tempactive) + { + Hunk_FreeToHighMark (hunk_tempmark); + hunk_tempactive = false; + } + + hunk_tempmark = Hunk_HighMark (); + + buf = Hunk_HighAllocName (size, "temp"); + + hunk_tempactive = true; + + return buf; +} + +/* +=============================================================================== + +CACHE MEMORY + +=============================================================================== +*/ + +typedef struct cache_system_s +{ + int size; // including this header + cache_user_t *user; + char name[16]; + struct cache_system_s *prev, *next; + struct cache_system_s *lru_prev, *lru_next; // for LRU flushing +} cache_system_t; + +cache_system_t *Cache_TryAlloc (int size, qboolean nobottom); + +cache_system_t cache_head; + +/* +=========== +Cache_Move +=========== +*/ +void Cache_Move ( cache_system_t *c) +{ + cache_system_t *new; + +// we are clearing up space at the bottom, so only allocate it late + new = Cache_TryAlloc (c->size, true); + if (new) + { +// Con_Printf ("cache_move ok\n"); + + Q_memcpy ( new+1, c+1, c->size - sizeof(cache_system_t) ); + new->user = c->user; + Q_memcpy (new->name, c->name, sizeof(new->name)); + Cache_Free (c->user); + new->user->data = (void *)(new+1); + } + else + { +// Con_Printf ("cache_move failed\n"); + + Cache_Free (c->user); // tough luck... + } +} + +/* +============ +Cache_FreeLow + +Throw things out until the hunk can be expanded to the given point +============ +*/ +void Cache_FreeLow (int new_low_hunk) +{ + cache_system_t *c; + + while (1) + { + c = cache_head.next; + if (c == &cache_head) + return; // nothing in cache at all + if ((byte *)c >= hunk_base + new_low_hunk) + return; // there is space to grow the hunk + Cache_Move ( c ); // reclaim the space + } +} + +/* +============ +Cache_FreeHigh + +Throw things out until the hunk can be expanded to the given point +============ +*/ +void Cache_FreeHigh (int new_high_hunk) +{ + cache_system_t *c, *prev; + + prev = NULL; + while (1) + { + c = cache_head.prev; + if (c == &cache_head) + return; // nothing in cache at all + if ( (byte *)c + c->size <= hunk_base + hunk_size - new_high_hunk) + return; // there is space to grow the hunk + if (c == prev) + Cache_Free (c->user); // didn't move out of the way + else + { + Cache_Move (c); // try to move it + prev = c; + } + } +} + +void Cache_UnlinkLRU (cache_system_t *cs) +{ + if (!cs->lru_next || !cs->lru_prev) + Sys_Error ("Cache_UnlinkLRU: NULL link"); + + cs->lru_next->lru_prev = cs->lru_prev; + cs->lru_prev->lru_next = cs->lru_next; + + cs->lru_prev = cs->lru_next = NULL; +} + +void Cache_MakeLRU (cache_system_t *cs) +{ + if (cs->lru_next || cs->lru_prev) + Sys_Error ("Cache_MakeLRU: active link"); + + cache_head.lru_next->lru_prev = cs; + cs->lru_next = cache_head.lru_next; + cs->lru_prev = &cache_head; + cache_head.lru_next = cs; +} + +/* +============ +Cache_TryAlloc + +Looks for a free block of memory between the high and low hunk marks +Size should already include the header and padding +============ +*/ +cache_system_t *Cache_TryAlloc (int size, qboolean nobottom) +{ + cache_system_t *cs, *new; + +// is the cache completely empty? + + if (!nobottom && cache_head.prev == &cache_head) + { + if (hunk_size - hunk_high_used - hunk_low_used < size) + Sys_Error ("Cache_TryAlloc: %i is greater then free hunk", size); + + new = (cache_system_t *) (hunk_base + hunk_low_used); + memset (new, 0, sizeof(*new)); + new->size = size; + + cache_head.prev = cache_head.next = new; + new->prev = new->next = &cache_head; + + Cache_MakeLRU (new); + return new; + } + +// search from the bottom up for space + + new = (cache_system_t *) (hunk_base + hunk_low_used); + cs = cache_head.next; + + do + { + if (!nobottom || cs != cache_head.next) + { + if ( (byte *)cs - (byte *)new >= size) + { // found space + memset (new, 0, sizeof(*new)); + new->size = size; + + new->next = cs; + new->prev = cs->prev; + cs->prev->next = new; + cs->prev = new; + + Cache_MakeLRU (new); + + return new; + } + } + + // continue looking + new = (cache_system_t *)((byte *)cs + cs->size); + cs = cs->next; + + } while (cs != &cache_head); + +// try to allocate one at the very end + if ( hunk_base + hunk_size - hunk_high_used - (byte *)new >= size) + { + memset (new, 0, sizeof(*new)); + new->size = size; + + new->next = &cache_head; + new->prev = cache_head.prev; + cache_head.prev->next = new; + cache_head.prev = new; + + Cache_MakeLRU (new); + + return new; + } + + return NULL; // couldn't allocate +} + +/* +============ +Cache_Flush + +Throw everything out, so new data will be demand cached +============ +*/ +void Cache_Flush (void) +{ + while (cache_head.next != &cache_head) + Cache_Free ( cache_head.next->user ); // reclaim the space +} + + +/* +============ +Cache_Print + +============ +*/ +void Cache_Print (void) +{ + cache_system_t *cd; + + for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next) + { + Con_Printf ("%8i : %s\n", cd->size, cd->name); + } +} + +/* +============ +Cache_Report + +============ +*/ +void Cache_Report (void) +{ + Con_DPrintf ("%4.1f megabyte data cache\n", (hunk_size - hunk_high_used - hunk_low_used) / (float)(1024*1024) ); +} + +/* +============ +Cache_Compact + +============ +*/ +void Cache_Compact (void) +{ +} + +/* +============ +Cache_Init + +============ +*/ +void Cache_Init (void) +{ + cache_head.next = cache_head.prev = &cache_head; + cache_head.lru_next = cache_head.lru_prev = &cache_head; + + Cmd_AddCommand ("flush", Cache_Flush); +} + +/* +============== +Cache_Free + +Frees the memory and removes it from the LRU list +============== +*/ +void Cache_Free (cache_user_t *c) +{ + cache_system_t *cs; + + if (!c->data) + Sys_Error ("Cache_Free: not allocated"); + + cs = ((cache_system_t *)c->data) - 1; + + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + cs->next = cs->prev = NULL; + + c->data = NULL; + + Cache_UnlinkLRU (cs); +} + + + +/* +============== +Cache_Check +============== +*/ +void *Cache_Check (cache_user_t *c) +{ + cache_system_t *cs; + + if (!c->data) + return NULL; + + cs = ((cache_system_t *)c->data) - 1; + +// move to head of LRU + Cache_UnlinkLRU (cs); + Cache_MakeLRU (cs); + + return c->data; +} + + +/* +============== +Cache_Alloc +============== +*/ +void *Cache_Alloc (cache_user_t *c, int size, char *name) +{ + cache_system_t *cs; + + if (c->data) + Sys_Error ("Cache_Alloc: allready allocated"); + + if (size <= 0) + Sys_Error ("Cache_Alloc: size %i", size); + + size = (size + sizeof(cache_system_t) + 15) & ~15; + +// find memory for it + while (1) + { + cs = Cache_TryAlloc (size, false); + if (cs) + { + strncpy (cs->name, name, sizeof(cs->name)-1); + c->data = (void *)(cs+1); + cs->user = c; + break; + } + + // free the least recently used cahedat + if (cache_head.lru_prev == &cache_head) + Sys_Error ("Cache_Alloc: out of memory"); + // not enough memory at all + Cache_Free ( cache_head.lru_prev->user ); + } + + return Cache_Check (c); +} + +//============================================================================ + + +/* +======================== +Memory_Init +======================== +*/ +void Memory_Init (void *buf, int size) +{ + int p; + int zonesize = DYNAMIC_SIZE; + + hunk_base = buf; + hunk_size = size; + hunk_low_used = 0; + hunk_high_used = 0; + + Cache_Init (); + p = COM_CheckParm ("-zone"); + if (p) + { + if (p < com_argc-1) + zonesize = Q_atoi (com_argv[p+1]) * 1024; + else + Sys_Error ("Memory_Init: you must specify a size in KB after -zone"); + } + mainzone = Hunk_AllocName (zonesize, "zone" ); + Z_ClearZone (mainzone, zonesize); +} + diff --git a/WinQuake/zone.h b/WinQuake/zone.h index 7655ad9..b63006f 100644 --- a/WinQuake/zone.h +++ b/WinQuake/zone.h @@ -1,131 +1,131 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -/* - memory allocation - - -H_??? The hunk manages the entire memory block given to quake. It must be -contiguous. Memory can be allocated from either the low or high end in a -stack fashion. The only way memory is released is by resetting one of the -pointers. - -Hunk allocations should be given a name, so the Hunk_Print () function -can display usage. - -Hunk allocations are guaranteed to be 16 byte aligned. - -The video buffers are allocated high to avoid leaving a hole underneath -server allocations when changing to a higher video mode. - - -Z_??? Zone memory functions used for small, dynamic allocations like text -strings from command input. There is only about 48K for it, allocated at -the very bottom of the hunk. - -Cache_??? Cache memory is for objects that can be dynamically loaded and -can usefully stay persistant between levels. The size of the cache -fluctuates from level to level. - -To allocate a cachable object - - -Temp_??? Temp memory is used for file loading and surface caching. The size -of the cache memory is adjusted so that there is a minimum of 512k remaining -for temp memory. - - ------- Top of Memory ------- - -high hunk allocations - -<--- high hunk reset point held by vid - -video buffer - -z buffer - -surface cache - -<--- high hunk used - -cachable memory - -<--- low hunk used - -client and server low hunk allocations - -<-- low hunk reset point held by host - -startup hunk allocations - -Zone block - ------ Bottom of Memory ----- - - - -*/ - -void Memory_Init (void *buf, int size); - -void Z_Free (void *ptr); -void *Z_Malloc (int size); // returns 0 filled memory -void *Z_TagMalloc (int size, int tag); - -void Z_DumpHeap (void); -void Z_CheckHeap (void); -int Z_FreeMemory (void); - -void *Hunk_Alloc (int size); // returns 0 filled memory -void *Hunk_AllocName (int size, char *name); - -void *Hunk_HighAllocName (int size, char *name); - -int Hunk_LowMark (void); -void Hunk_FreeToLowMark (int mark); - -int Hunk_HighMark (void); -void Hunk_FreeToHighMark (int mark); - -void *Hunk_TempAlloc (int size); - -void Hunk_Check (void); - -typedef struct cache_user_s -{ - void *data; -} cache_user_t; - -void Cache_Flush (void); - -void *Cache_Check (cache_user_t *c); -// returns the cached data, and moves to the head of the LRU list -// if present, otherwise returns NULL - -void Cache_Free (cache_user_t *c); - -void *Cache_Alloc (cache_user_t *c, int size, char *name); -// Returns NULL if all purgable data was tossed and there still -// wasn't enough room. - -void Cache_Report (void); - - - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +/* + memory allocation + + +H_??? The hunk manages the entire memory block given to quake. It must be +contiguous. Memory can be allocated from either the low or high end in a +stack fashion. The only way memory is released is by resetting one of the +pointers. + +Hunk allocations should be given a name, so the Hunk_Print () function +can display usage. + +Hunk allocations are guaranteed to be 16 byte aligned. + +The video buffers are allocated high to avoid leaving a hole underneath +server allocations when changing to a higher video mode. + + +Z_??? Zone memory functions used for small, dynamic allocations like text +strings from command input. There is only about 48K for it, allocated at +the very bottom of the hunk. + +Cache_??? Cache memory is for objects that can be dynamically loaded and +can usefully stay persistant between levels. The size of the cache +fluctuates from level to level. + +To allocate a cachable object + + +Temp_??? Temp memory is used for file loading and surface caching. The size +of the cache memory is adjusted so that there is a minimum of 512k remaining +for temp memory. + + +------ Top of Memory ------- + +high hunk allocations + +<--- high hunk reset point held by vid + +video buffer + +z buffer + +surface cache + +<--- high hunk used + +cachable memory + +<--- low hunk used + +client and server low hunk allocations + +<-- low hunk reset point held by host + +startup hunk allocations + +Zone block + +----- Bottom of Memory ----- + + + +*/ + +void Memory_Init (void *buf, int size); + +void Z_Free (void *ptr); +void *Z_Malloc (int size); // returns 0 filled memory +void *Z_TagMalloc (int size, int tag); + +void Z_DumpHeap (void); +void Z_CheckHeap (void); +int Z_FreeMemory (void); + +void *Hunk_Alloc (int size); // returns 0 filled memory +void *Hunk_AllocName (int size, char *name); + +void *Hunk_HighAllocName (int size, char *name); + +int Hunk_LowMark (void); +void Hunk_FreeToLowMark (int mark); + +int Hunk_HighMark (void); +void Hunk_FreeToHighMark (int mark); + +void *Hunk_TempAlloc (int size); + +void Hunk_Check (void); + +typedef struct cache_user_s +{ + void *data; +} cache_user_t; + +void Cache_Flush (void); + +void *Cache_Check (cache_user_t *c); +// returns the cached data, and moves to the head of the LRU list +// if present, otherwise returns NULL + +void Cache_Free (cache_user_t *c); + +void *Cache_Alloc (cache_user_t *c, int size, char *name); +// Returns NULL if all purgable data was tossed and there still +// wasn't enough room. + +void Cache_Report (void); + + + -- cgit v1.2.3